如何实现类似https://boy-coy.com/#home的平滑滚动并调整视差速度
实现平滑滚动与调整视差滚动速度方案
一、基础平滑滚动实现
如果需要像目标站点那样的定制化平滑滚动,仅靠CSS的scroll-behavior: smooth可能不够灵活,推荐使用JavaScript结合requestAnimationFrame实现可控的缓动效果:
let isScrolling = false; const scrollDuration = 800; // 滚动总时长(单位:ms),数值越大滚动越平缓 function smoothScrollTo(targetY) { const startY = window.scrollY; const distance = targetY - startY; let startTime = null; function animation(currentTime) { if (!startTime) startTime = currentTime; const timeElapsed = currentTime - startTime; const progress = Math.min(timeElapsed / scrollDuration, 1); // 使用ease-in-out缓动函数,让滚动更自然 const easedProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2; const currentScroll = startY + distance * easedProgress; window.scrollTo(0, currentScroll); if (timeElapsed < scrollDuration) { requestAnimationFrame(animation); } else { isScrolling = false; } } isScrolling = true; requestAnimationFrame(animation); } // 监听锚点链接点击(示例) document.querySelectorAll('a[href^="#"]').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetElement = document.querySelector(link.getAttribute('href')); if (targetElement && !isScrolling) { const targetY = targetElement.getBoundingClientRect().top + window.scrollY; smoothScrollTo(targetY); } }); });
调整scrollDuration的值即可控制滚动速度,数值越大,滚动过程越慢、越平滑。
二、视差效果速度调整
视差效果的核心是滚动位移与元素位移的比例系数,系数越小,视差移动越慢,反之则越快。
1. CSS背景视差场景
如果用CSS实现背景图视差,修改background-position中的滚动系数:
.parallax-section { background-image: url('你的背景图地址'); background-attachment: fixed; background-position: center calc(50% + var(--scroll-y) * 0.1); /* 0.1为视差系数,调小则效果更平缓 */ background-size: cover; }
同时需要JS实时计算滚动值并更新CSS变量:
window.addEventListener('scroll', () => { if (!isScrolling) { // 避免与平滑滚动逻辑冲突 document.documentElement.style.setProperty('--scroll-y', window.scrollY); } });
将0.1改成更小的数值(比如0.05),视差移动速度会明显变慢;如果是元素位移的视差,同理调整transform的系数即可。
2. JavaScript控制的元素视差
如果通过JS控制元素位移实现视差,直接调整位移计算的系数:
const parallaxElements = document.querySelectorAll('.parallax-element'); function updateParallax(currentScroll) { parallaxElements.forEach(el => { const speed = parseFloat(el.dataset.speed) || 0.1; // 从元素data属性读取系数,默认0.1 el.style.transform = `translateY(${currentScroll * speed}px)`; }); } // 结合平滑滚动,在动画中同步更新视差 function animation(currentTime) { // ... 保留之前的平滑滚动逻辑 ... const currentScroll = startY + distance * easedProgress; updateParallax(currentScroll); // 使用平滑后的滚动值计算视差,避免不同步 // ... } // 原生滚动时也同步更新视差 window.addEventListener('scroll', () => { if (!isScrolling) { updateParallax(window.scrollY); } });
在HTML元素上可以通过data-speed属性单独设置每个元素的视差速度:
<div class="parallax-element" data-speed="0.08"></div>
三、同步平滑滚动与视差的关键
当使用自定义平滑滚动时,必须用平滑动画中的实时滚动值计算视差,而不是原生的window.scrollY,否则会出现视差与滚动动作不同步的情况。上面的代码已经包含了这一逻辑,确保两者的进度完全匹配。
内容的提问来源于stack exchange,提问作者Param
相关产品推荐
相关产品推荐

