在制作产品展示、官网首屏等全屏类页面时,垂直全屏滑块配合鼠标滚轮单页切换是提升用户体验的常用方案,Splide.js作为一款轻量且扩展性强的滑块库,能够高效实现这个需求。接下来将一步步讲解完整的实现过程。

环境准备与基础引入
首先需要在项目中引入Splide.js的相关资源,你可以选择通过CDN引入,也可以下载文件到本地引用。这里以CDN方式为例,在HTML的<head>标签中添加样式文件,在<body>结束前添加脚本文件。
<!-- 引入Splide.js样式 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css"> <!-- 引入Splide.js核心脚本 --> <script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>
HTML结构搭建
全屏滑块需要让每个滑块项占满整个视口,因此HTML结构需要设置对应的容器层级。基础结构如下,每个<li>标签对应一个全屏页面内容。
<div class="splide" id="vertical-fullscreen-slider">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<div class="slide-content">第一屏内容</div>
</li>
<li class="splide__slide">
<div class="slide-content">第二屏内容</div>
</li>
<li class="splide__slide">
<div class="slide-content">第三屏内容</div>
</li>
</ul>
</div>
</div>
CSS样式配置
要实现垂直全屏效果,需要给滑块容器和每个滑块项设置全屏相关的样式,同时调整Splide.js默认的横向布局为垂直布局。
/* 重置基础样式,避免默认边距影响全屏效果 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
overflow: hidden; /* 隐藏默认滚动条,由滑块控制滚动 */
}
/* 滑块容器占满全屏 */
#vertical-fullscreen-slider {
height: 100vh;
}
/* 滑块轨道高度跟随容器 */
.splide__track {
height: 100%;
}
/* 每个滑块项占满全屏 */
.splide__slide {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* 滑块内容样式自定义 */
.slide-content {
font-size: 32px;
color: #333;
}
Splide.js核心配置
接下来初始化Splide.js实例,需要重点配置垂直方向、全屏相关参数,同时关闭默认的循环滚动,确保单页切换的效果。
// 初始化Splide实例
const splide = new Splide('#vertical-fullscreen-slider', {
type: 'slide', // 滑动类型,不使用淡入淡出
direction: 'ttb', // 垂直方向,top to bottom
height: '100vh', // 滑块高度占满视口
perPage: 1, // 每页显示1个滑块
perMove: 1, // 每次移动1个滑块,实现单页切换
wheel: false, // 先关闭默认滚轮,后续自定义控制
releaseWheel: false, // 不释放滚轮事件
speed: 800, // 滑动动画时长
easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', // 滑动缓动函数
pagination: true, // 显示分页指示器
arrows: false, // 隐藏左右箭头,垂直场景不需要
drag: true, // 允许触摸拖拽
dragAngleThreshold: 60, // 拖拽角度阈值,避免横向误触
});
splide.mount();
鼠标滚轮单页滑动控制实现
Splide.js默认的滚轮控制可能不符合单页切换的需求,因此需要自定义滚轮事件监听,控制滑块每次只切换一页,同时避免快速滚动导致的多页跳转。
// 节流函数,避免滚轮事件触发过于频繁
function throttle(fn, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
}
// 处理滚轮事件
const handleWheel = throttle((e) => {
e.preventDefault(); // 阻止默认滚动行为
// 判断滚轮方向,deltaY大于0向下滚动,小于0向上滚动
if (e.deltaY > 0) {
splide.go('>'); // 切换到下一页
} else {
splide.go('<'); // 切换到上一页
}
}, 800); // 节流间隔和滑动动画时长保持一致,避免冲突
// 监听滚轮事件,绑定到滑块容器上
const sliderContainer = document.getElementById('vertical-fullscreen-slider');
sliderContainer.addEventListener('wheel', handleWheel, { passive: false });
功能优化与注意事项
在实际使用中,还可以根据需求做一些优化调整:
- 如果需要添加键盘上下键控制,可以额外监听
keydown事件,按下上键调用splide.go('<'),下键调用splide.go('>') - 如果页面中有其他需要滚动的区域,可以通过判断事件触发目标,避免滑块容器外的滚轮事件被拦截
- 移动端场景下,Splide.js自带的触摸拖拽已经能实现垂直滑动,不需要额外处理触摸事件
- 如果需要添加页面切换的回调,可以监听Splide的
move事件,在回调中执行对应的业务逻辑
完整示例代码
以下是整合所有功能的完整可运行代码,你可以直接复制到HTML文件中测试效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Splide.js垂直全屏滑块</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
overflow: hidden;
}
#vertical-fullscreen-slider {
height: 100vh;
}
.splide__track {
height: 100%;
}
.splide__slide {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.slide-content {
font-size: 32px;
color: #333;
}
/* 不同滑块背景色区分 */
.splide__slide:nth-child(1) { background-color: #f0f8ff; }
.splide__slide:nth-child(2) { background-color: #f5f5dc; }
.splide__slide:nth-child(3) { background-color: #ffe4e1; }
</style>
</head>
<body>
<div class="splide" id="vertical-fullscreen-slider">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">
<div class="slide-content">第一屏内容</div>
</li>
<li class="splide__slide">
<div class="slide-content">第二屏内容</div>
</li>
<li class="splide__slide">
<div class="slide-content">第三屏内容</div>
</li>
</ul>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>
<script>
const splide = new Splide('#vertical-fullscreen-slider', {
type: 'slide',
direction: 'ttb',
height: '100vh',
perPage: 1,
perMove: 1,
wheel: false,
releaseWheel: false,
speed: 800,
easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
pagination: true,
arrows: false,
drag: true,
dragAngleThreshold: 60,
});
splide.mount();
function throttle(fn, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
}
const handleWheel = throttle((e) => {
e.preventDefault();
if (e.deltaY > 0) {
splide.go('>');
} else {
splide.go('<');
}
}, 800);
const sliderContainer = document.getElementById('vertical-fullscreen-slider');
sliderContainer.addEventListener('wheel', handleWheel, { passive: false });
</script>
</body>
</html>