在现代网页设计中,全屏滚动网站已经成为一种流行的设计趋势。这种交互方式能够提供沉浸式的用户体验,让用户专注于当前屏幕的内容,同时通过流畅的动画过渡增强视觉吸引力。本文将介绍如何使用 HTML、CSS 和 JavaScript 构建一个功能完整的全屏滚动网页。效果演示
这个网页具有以下特性:
平滑的页面切换动画效果
右侧圆形导航指示器,可点击跳转到指定页面
支持鼠标滚轮、键盘方向键、触摸滑动等多种操作方式
响应式设计,适配不同设备屏幕
页面内容进入时带动画效果,提升视觉体验
循环滚动模式,到达最后一页后可回到第一页
页面结构
主容器结构
主容器 fullpage-wrapper 包含多个 section 元素,每个 section 代表一个全屏页面。当前激活的页面带有 active 类。<div class="fullpage-wrapper" id="fullpage"> <div class="section active"> <div class="section-content"> <h2>欢迎来到全屏滚动</h2> <p>体验流畅的全屏滚动效果</p> </div> </div> </div>
导航和控件
右侧的 navigation 区域用于放置导航点,底部的 scroll-indicator 提供滚动提示。<div class="navigation" id="navigation"></div><div class="scroll-indicator" id="scrollIndicator">向下滚动</div>
核心功能实现
初始化过程
initFullPage 函数负责初始化整个全屏滚动系统:获取页面元素引用;设置过渡动画效果;创建导航点;绑定各种事件监听器;更新初始状态。function initFullPage() { fullpageState.wrapper = document.getElementById('fullpage'); fullpageState.sections = fullpageState.wrapper.querySelectorAll('.section'); fullpageState.wrapper.style.transition = `transform ${fullpageState.duration}ms cubic-bezier(0.645, 0.045, 0.355, 1)`; if (fullpageState.navigation) createNavigation(); bindEvents(); updateActive(); updateScrollIndicator();}
页面切换逻辑
goTo 函数负责实现页面切换,它会计算目标位置并触发动画效果。function goTo(index) { if (fullpageState.isScrolling || index === fullpageState.currentIndex || index < 0 || index >= fullpageState.sections.length) return; fullpageState.currentIndex = index; fullpageState.isScrolling = true;
updateTransform(); updateActive(); updateScrollIndicator();
setTimeout(() => { fullpageState.isScrolling = false; }, fullpageState.duration);}
事件处理机制
系统支持多种用户交互方式:
鼠标滚轮事件:通过 wheel 事件监听垂直滚动方向
键盘控制:监听方向键、PageUp/PageDown、Home/End 等按键
触摸操作:在移动设备上支持滑动切换页面
窗口大小调整:自动适应屏幕变化
function bindEvents() { window.addEventListener('wheel', handleWheel); if (fullpageState.keyboard) { window.addEventListener('keydown', handleKeydown); } window.addEventListener('touchstart', handleTouchStart,); window.addEventListener('touchend', handleTouchEnd); window.addEventListener('resize', updateTransform);}
扩展建议
自动播放功能:添加定时器实现页面自动切换
水平滚动支持:扩展为支持横向滚动的幻灯片效果
进度条显示:在顶部或底部添加滚动进度条
锚点链接支持:通过URL锚点直接访问特定页面
回调函数扩展:增加页面切换前后的回调函数支持
主题定制:提供多种动画效果和主题样式供选择
完整代码
git地址:https://gitee.com/ironpro/hjdemo/blob/master/fullpage/index.html<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>全屏滚动</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { overflow: hidden; } .fullpage-wrapper { position: relative; transition: transform 0.8s cubic-bezier(0.645, 0.045, 0.355, 1); height: 100vh; } .section { position: relative; width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; font-size: 3rem; color: white; text-align: center; } .section:nth-child(1) { background: linear-gradient(128deg,#40afff,#3f61ff); } .section:nth-child(2) { background: linear-gradient(128deg,#ff9a3f,#ff4b40); } .section:nth-child(3) { background: linear-gradient(128deg,#fc40ff,#543fff); } .section:nth-child(4) { background: linear-gradient(128deg,#43e97b,#38f9d7); } .section:nth-child(5) { background: linear-gradient(128deg,#fa709a,#fee140); }
.section-content { max-width: 800px; padding: 2rem; } .section h2 { font-size: 4rem; margin-bottom: 1rem; opacity: 0; transform: translateY(50px); transition: all 0.8s ease; } .section p { font-size: 1.5rem; opacity: 0; transform: translateY(30px); transition: all 0.8s ease 0.2s; } .section.active h2, .section.active p { opacity: 1; transform: translateY(0); } .navigation { position: fixed; right: 30px; top: 50%; transform: translateY(-50%); z-index: 1000; } .nav-dot { width: 14px; height: 14px; border-radius: 50%; background: rgba(255, 255, 255, 0.5); margin: 15px 0; cursor: pointer; transition: all 0.3s ease; border: 2px solid transparent; } .nav-dot.active { background: white; transform: scale(1.3); border-color: rgba(255, 255, 255, 0.3); } .nav-dot:hover { background: rgba(255, 255, 255, 0.8); transform: scale(1.2); } .scroll-indicator { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); color: white; font-size: 0.9rem; opacity: 0.7; animation: bounce 2s infinite; z-index: 1000; } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateX(-50%) translateY(0); } 40% { transform: translateX(-50%) translateY(-10px); } 60% { transform: translateX(-50%) translateY(-5px); } } @media (max-width: 768px) { .section h2 { font-size: 2.3rem; } .section p { font-size: 1.2rem; } .navigation { right: 15px; } } </style></head><body><div class="fullpage-wrapper" id="fullpage"> <div class="section active"> <div class="section-content"> <h2>欢迎来到全屏滚动</h2> <p>体验流畅的全屏滚动效果</p> </div> </div> <div class="section"> <div class="section-content"> <h2>响应式设计</h2> <p>完美适配各种设备,手机、平板、桌面都能完美显示</p> </div> </div> <div class="section"> <div class="section-content"> <h2>动画效果</h2> <p>丰富的动画效果,让页面切换更加生动有趣</p> </div> </div> <div class="section"> <div class="section-content"> <h2>简单易用</h2> <p>简洁的设计,轻松集成到任何项目中</p> </div> </div> <div class="section"> <div class="section-content"> <h2>开始体验</h2> <p>滚动鼠标、点击导航或使用键盘方向键来体验</p> </div> </div></div>
<div class="navigation" id="navigation"></div><div class="scroll-indicator" id="scrollIndicator">向下滚动</div><script> var fullpageState = { currentIndex: 0, isScrolling: false, sections: [], wrapper: null, duration: 800, loop: true, keyboard: true, navigation: true }; function initFullPage() { fullpageState.wrapper = document.getElementById('fullpage'); fullpageState.sections = fullpageState.wrapper.querySelectorAll('.section'); fullpageState.wrapper.style.transition = `transform ${fullpageState.duration}ms cubic-bezier(0.645, 0.045, 0.355, 1)`; if (fullpageState.navigation) createNavigation(); bindEvents(); updateActive(); updateScrollIndicator(); } function createNavigation() { var nav = document.getElementById('navigation'); nav.innerHTML = ''; fullpageState.sections.forEach((_, index) => { var dot = document.createElement('div'); dot.className = 'nav-dot'; dot.addEventListener('click', () => goTo(index)); nav.appendChild(dot); }); } function bindEvents() { window.addEventListener('wheel', handleWheel); if (fullpageState.keyboard) { window.addEventListener('keydown', handleKeydown); } window.addEventListener('touchstart', handleTouchStart,); window.addEventListener('touchend', handleTouchEnd); window.addEventListener('resize', updateTransform); } function handleWheel(e) { e.preventDefault(); if (fullpageState.isScrolling) return; e.deltaY > 0 ? next() : prev(); }
function handleKeydown(e) { if (fullpageState.isScrolling) return; switch(e.key) { case 'ArrowDown': case 'PageDown': e.preventDefault(); next(); break; case 'ArrowUp': case 'PageUp': e.preventDefault(); prev(); break; case 'Home': e.preventDefault(); goTo(0); break; case 'End': e.preventDefault(); goTo(fullpageState.sections.length - 1); break; } }
function handleTouchStart(e) { fullpageState.touchStartY = e.touches[0].clientY; }
function handleTouchEnd(e) { if (fullpageState.isScrolling) return; var diff = fullpageState.touchStartY - e.changedTouches[0].clientY; if (Math.abs(diff) > 50) { diff > 0 ? next() : prev(); } } function next() { if (fullpageState.isScrolling) return; var nextIndex = fullpageState.currentIndex + 1;
if (nextIndex >= fullpageState.sections.length) { nextIndex = fullpageState.loop ? 0 : fullpageState.sections.length - 1; } goTo(nextIndex); }
function prev() { if (fullpageState.isScrolling) return; var prevIndex = fullpageState.currentIndex - 1;
if (prevIndex < 0) { prevIndex = fullpageState.loop ? fullpageState.sections.length - 1 : 0; } goTo(prevIndex); } function goTo(index) { if (fullpageState.isScrolling || index === fullpageState.currentIndex || index < 0 || index >= fullpageState.sections.length) return; fullpageState.currentIndex = index; fullpageState.isScrolling = true;
updateTransform(); updateActive(); updateScrollIndicator();
setTimeout(() => { fullpageState.isScrolling = false; }, fullpageState.duration); }
function updateTransform() { var translateY = -fullpageState.currentIndex * 100; fullpageState.wrapper.style.transform = `translateY(${translateY}vh)`; } function updateActive() { fullpageState.sections.forEach((section, index) => { section.classList.toggle('active', index === fullpageState.currentIndex); });
if (fullpageState.navigation) { var dots = document.querySelectorAll('.nav-dot'); dots.forEach((dot, index) => { dot.classList.toggle('active', index === fullpageState.currentIndex); }); } }
function updateScrollIndicator() { var indicator = document.getElementById('scrollIndicator'); if (fullpageState.currentIndex === fullpageState.sections.length - 1) { indicator.style.display = 'none'; } else { indicator.style.display = 'block'; indicator.textContent = fullpageState.currentIndex === 0 ? '向下滚动' : '继续滚动'; } } initFullPage();</script></body></html>
阅读原文:https://mp.weixin.qq.com/s/yka4RMinISF2xp8iGLjNbw
该文章在 2025/12/19 12:03:22 编辑过