如何为基于requestAnimationFrame的JS页面滚动添加缓入缓出效果?
实现带Ease-in-out效果的平滑滚动
方案说明
针对你现有基于requestAnimationFrame的滚动方案,我们可以通过缓动函数实现自然的缓入缓出效果,核心是让滚动速度从缓慢起步,加速到中间后再减速停止,替代固定步长的滚动方式。
完整实现代码
HTML(保持原结构)
<div id="container"> <section class="sect sect-1"> <p>Section 1</p> </section> <section class="sect sect-2"> <p>Section 2</p> </section> <section id="test-div" class="sect sect-3"> <p>Section 3</p> </section> <section class="sect sect-4"> <p>Section 4</p> </section> </div>
CSS(保持原样式)
* { padding: 0px; margin: 0px; outline: none; font-size: 100%; font: inherit; vertical-align: baseline; } *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; -webkit-font-smoothing: antialiased; font-smoothing: antialiased; text-rendering: optimizeLegibility; } #container { min-height: 100vh; background: #777; display: flex; flex-direction: column; background: #000; } p, h1, h2, h3, h4, h5 { color: #fff; font-family: monospace; } .sect { border: solid 0px #fff; display: flex; min-height: 100vh; display: flex; align-items: center; justify-content: center; } .sect-1 { background: #666; } .sect-2 { background: #333; } .sect-3 { background: #666; } .sect-4 { background: #333; }
JavaScript(修改后带缓动效果)
// 目标元素 const targetEl = document.getElementById('test-div'); // 动画持续时间(可根据需求调整,单位:毫秒) const scrollDuration = 1200; // 二次缓入缓出函数:实现速度从慢到快再变慢的效果 function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; } function smoothScrollWithEase() { const startScrollPos = window.scrollY; const targetScrollPos = targetEl.offsetTop; const totalScrollDistance = targetScrollPos - startScrollPos; let animationStartTime = null; // 动画帧处理函数 function animateScroll(currentTime) { if (!animationStartTime) animationStartTime = currentTime; // 计算已流逝时间占总时长的比例(0到1之间) const timeProgress = Math.min((currentTime - animationStartTime) / scrollDuration, 1); // 应用缓动函数,得到经过缓动后的进度值 const easedProgress = easeInOutQuad(timeProgress); // 计算当前应该滚动到的位置 const currentPos = startScrollPos + totalScrollDistance * easedProgress; // 执行滚动 window.scrollTo(0, currentPos); // 未完成则继续下一帧动画 if (timeProgress < 1) { requestAnimationFrame(animateScroll); } } requestAnimationFrame(animateScroll); } // 1秒后触发滚动动画 setTimeout(smoothScrollWithEase, 1000);
关键细节说明
- 缓动函数:
easeInOutQuad是经典的二次缓入缓动公式,t为0到1的进度值,返回经过缓动后的进度,实现速度的平滑变化。 - 动画控制:通过记录动画开始时间,计算每帧的进度比例,结合缓动函数得到当前滚动位置,替代原固定步长的
scrollBy,避免生硬的匀速滚动。 - 可定制性:调整
scrollDuration可以直接控制滚动的快慢,数值越大滚动越慢,反之越快。
内容的提问来源于stack exchange,提问作者UllerUller
相关产品推荐
相关产品推荐

