门户网站中往往有比较多的特效,其中鼠标纵向滚屏翻页就是一种比较常见的效果,接下来我们用两种版本来实现这个效果
html+css+js版本效果演示
html+css+js版本代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>纵向滚屏翻页</title>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.section {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
transition: transform 0.5s ease;
}
.section:nth-child(1) { background-color: #FFA726; }
.section:nth-child(2) { background-color: #F57C00; }
.section:nth-child(3) { background-color: #EF6C00; }
.pagination {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
.pagination li {
list-style: none;
margin: 10px 0;
cursor: pointer;
width: 10px;
height: 10px;
background-color: #8D6E63;
border-radius: 50%;
}
.pagination li.active {
background-color: #FFF3E0;
}
</style>
</head>
<body>
<div class="sections">
<div class="section">页面 1</div>
<div class="section">页面 2</div>
<div class="section">页面 3</div>
</div>
<ul class="pagination">
<li></li>
<li></li>
<li></li>
</ul>
<script>
const sections = document.querySelectorAll('.section');
const paginationDots = document.querySelectorAll('.pagination li');
let currentSectionIndex = 0;
function scrollToSection(index) {
sections.forEach((section, i) => {
section.style.transform = `translateY(-${index * 100}vh)`;
});
paginationDots.forEach(dot => dot.classList.remove('active'));
paginationDots[index].classList.add('active');
currentSectionIndex = index;
}
paginationDots.forEach((dot, index) => {
dot.addEventListener('click', () => scrollToSection(index));
});
document.addEventListener('keydown', (event) => {
if (event.key === 'ArrowDown' && currentSectionIndex < sections.length - 1) {
scrollToSection(currentSectionIndex + 1);
} else if (event.key === 'ArrowUp' && currentSectionIndex > 0) {
scrollToSection(currentSectionIndex - 1);
}
});
document.addEventListener('wheel', (event) => {
if (event.deltaY > 0 && currentSectionIndex < sections.length - 1) {
scrollToSection(currentSectionIndex + 1);
} else if (event.deltaY < 0 && currentSectionIndex > 0) {
scrollToSection(currentSectionIndex - 1);
}
});
scrollToSection(0);
</script>
</body>
</html>
vue3版本版本效果演示
vue3版本代码实现
<template>
<div
class="container"
@wheel.prevent="handleWheel"
@keydown="handleKeydown"
tabindex="0"
>
<div
class="section"
v-for="(section, index) in sections"
:key="index"
:style="{ backgroundColor: section.color }"
>
<h1>{{ section.title }}</h1>
</div>
<div class="pagination">
<div
class="dot"
v-for="(section, index) in sections"
:key="index"
:class="{ active: currentIndex === index }"
@click="scrollToSection(index)"
></div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const sections = ref([
{ title: '页面 1', color: '#FFA726' },
{ title: '页面 2', color: '#F57C00' },
{ title: '页面 3', color: '#EF6C00' },
])
const currentIndex = ref(0)
const scrollToSection = (index: number) => {
currentIndex.value = index
const container = document.querySelector('.container') as HTMLElement
container.style.transform = `translateY(-${index * 100}vh)`
}
const handleWheel = (event: WheelEvent) => {
if (event.deltaY > 0 && currentIndex.value < sections.value.length - 1) {
scrollToSection(currentIndex.value + 1)
} else if (event.deltaY < 0 && currentIndex.value > 0) {
scrollToSection(currentIndex.value - 1)
}
}
const handleKeydown = (event: KeyboardEvent) => {
if (
event.key === 'ArrowDown' &&
currentIndex.value < sections.value.length - 1
) {
scrollToSection(currentIndex.value + 1)
} else if (event.key === 'ArrowUp' && currentIndex.value > 0) {
scrollToSection(currentIndex.value - 1)
}
}
onMounted(() => {
const container = document.querySelector('.container') as HTMLElement
container.focus() // 自动聚焦容器以接收键盘事件
})
</script>
<style scoped>
.container {
position: relative;
height: 100vh;
overflow: hidden;
outline: none; /* 移除键盘聚焦时的轮廓 */
}
.section {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 2rem;
transition: transform 0.5s ease;
}
.pagination {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
.dot {
width: 10px;
height: 10px;
background-color: #8d6e63;
border-radius: 50%;
margin: 10px 0;
cursor: pointer;
}
.dot.active {
background-color: #fff3e0;
}
</style>
后续优化 (留给所需要的人去干吧)
对滚轮和键盘事件添加防抖优化,以提高性能并防止事件过于频繁地触发
- 防抖函数: 添加了一个
debounce函数,接受一个函数和延迟时间作为参数,确保在指定时间内不会重复触发函数。 - 应用于事件处理: 在
handleWheel和handleKeydown函数上应用该防抖处理,以避免因滚动或按键事件过于频繁而导致的性能下降。