You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为基于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);

关键细节说明

  1. 缓动函数:easeInOutQuad是经典的二次缓入缓动公式,t为0到1的进度值,返回经过缓动后的进度,实现速度的平滑变化。
  2. 动画控制:通过记录动画开始时间,计算每帧的进度比例,结合缓动函数得到当前滚动位置,替代原固定步长的scrollBy,避免生硬的匀速滚动。
  3. 可定制性:调整scrollDuration可以直接控制滚动的快慢,数值越大滚动越慢,反之越快。

内容的提问来源于stack exchange,提问作者UllerUller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:07:13