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

如何在滚动时应用缓动过渡效果?不使用jQuery

不用jQuery实现滚动缓动过渡的方案(附代码拆解)

嘿,我来帮你把这段看起来有点绕的原生JS滚动代码拆解清楚,同时给你讲明白不用jQuery怎么实现平滑滚动的核心逻辑~

核心原理

原生JS实现滚动缓动,本质就是逐帧修改页面的滚动位置,配合缓动函数让滚动速度呈现自然的加速/减速曲线,而不是瞬间跳到目标位置。常用的实现方式是用requestAnimationFrame(比setTimeout更流畅,和浏览器刷新同步)或者setTimeout来循环更新scrollTop值。


拆解你找到的那段脚本

先把完整的代码补全(你给的easeInOutQ...应该是easeInOutQuart),然后逐部分解释:

function scrollTo(c,e,d){
  d||(d=easeInOutQuart); // 若没传缓动函数,默认用easeInOutQuart
  var a=document.documentElement;
  // 兼容性处理:判断当前浏览器的滚动根元素是documentElement还是body
  if(0===a.scrollTop){
    var b=a.scrollTop;
    ++a.scrollTop;
    a=b+1===a.scrollTop--?a:document.body
  }
  b=a.scrollTop; // 获取当前滚动位置
  // 处理参数:如果传的是DOM元素,取它的offsetTop作为目标位置
  0>=e||("object"===typeof b&&(b=b.offsetTop),"object"===typeof c&&(c=c.offsetTop),
  // 内部自执行函数,负责动画循环
  function(a,b,c,f,d,e,h){
    function g(){
      // 如果进度超出范围,直接跳到目标位置;否则计算当前滚动位置
      0>f||1<f||0>=d?a.scrollTop=c:(a.scrollTop=b-(b-c)*h(f),f+=d*e,setTimeout(g,e))
    }
    g()
  }(a,b,c,0,1/e,20,d))
};

// 完整的缓动函数:先加速、后减速的四次方曲线
function easeInOutQuart(t) {
  return t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;
}

关键部分解释:

  1. 兼容性处理:
    老浏览器里,滚动根元素可能是document.documentElement(比如Chrome)或者document.body(比如老IE),这段代码通过临时修改scrollTop来判断哪个元素能生效。

  2. 参数处理:

    • c可以是目标滚动的像素值,也可以是DOM元素(自动取元素的offsetTop)
    • e是动画持续时间(毫秒)
    • d是自定义缓动函数,默认用easeInOutQuart
  3. 动画循环:
    用setTimeout每20ms执行一次g(),每次计算当前的滚动进度f(从0到1),然后用缓动函数h(f)把进度转换成符合动画曲线的值,最后修改scrollTop。


更易理解的简化版实现

上面的代码为了兼容性写得比较紧凑,这里给你一个更清晰的版本,用requestAnimationFrame实现更流畅的滚动:

// 定义缓动函数:先加速后减速,让滚动更自然
function easeInOutQuart(progress) {
  return progress < 0.5 
    ? 8 * Math.pow(progress, 4) 
    : 1 - Math.pow(-2 * progress + 2, 4) / 2;
}

// 平滑滚动函数
function smoothScrollTo(target, duration = 500) {
  // 获取当前滚动位置
  const startScroll = window.pageYOffset || document.documentElement.scrollTop;
  // 处理目标:如果是DOM元素,取它的顶部偏移量;如果是数字直接用
  const targetScroll = typeof target === 'object' ? target.offsetTop : target;
  const scrollDistance = targetScroll - startScroll;
  let startTime = null;

  // 动画核心:用requestAnimationFrame同步浏览器刷新
  function animate(currentTime) {
    if (!startTime) startTime = currentTime;
    // 计算已过去的时间占总时长的比例(进度0-1)
    const timeElapsed = currentTime - startTime;
    const progress = Math.min(timeElapsed / duration, 1);
    // 应用缓动函数,得到缓动后的进度
    const easedProgress = easeInOutQuart(progress);
    // 更新滚动位置
    window.scrollTo(0, startScroll + scrollDistance * easedProgress);
    
    // 如果动画还没结束,继续调用
    if (timeElapsed < duration) {
      requestAnimationFrame(animate);
    }
  }

  requestAnimationFrame(animate);
}

// 使用示例
// 1. 滚动到id为"about-section"的元素,持续600ms
smoothScrollTo(document.getElementById('about-section'), 600);
// 2. 直接滚动到Y轴1200px的位置,用默认500ms时长
smoothScrollTo(1200);

缓动函数的作用

缓动函数决定了滚动的速度变化曲线,比如:

  • easeInOutQuart:先缓慢加速,到中间后缓慢减速,滚动体验最自然
  • 你也可以换成其他缓动函数,比如匀速(function(t){return t})、先快后慢(easeOutQuart)等,只需要修改easeInOutQuart的实现即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:14:03