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

如何在不使用jQuery的情况下应用该缓动过渡效果?

原生JavaScript实现滚动缓动过渡效果(附代码解析)

嘿,我来帮你拆解这段原生JS的滚动缓动代码,同时讲清楚不用jQuery怎么实现这类平滑滚动效果~

首先,先明确核心逻辑:原生JS实现缓动滚动,本质是通过分多次修改scrollTop值,每次的位移量由「缓动函数」计算,让滚动从快到慢(或先加速后减速),而不是一次性跳转到目标位置。

先拆解你找到的那段脚本

我们逐部分来看这个scrollTo函数:

function scrollTo(c,e,d){
  // 设置默认缓动函数为easeInOutQuart
  d||(d=easeInOutQuart);
  var a=document.documentElement;
  // 兼容性处理:判断用document.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))
};

关键细节解析:

  1. 滚动容器兼容性处理:
    不同浏览器的scrollTop挂载对象不一样——有些在document.documentElement,有些在document.body。这段代码通过一个小测试(尝试修改documentElement.scrollTop看是否生效),自动选择正确的滚动容器,避免兼容性问题。

  2. 参数灵活性:
    函数支持两种传参方式:

    • 直接传数值:比如scrollTo(1000, 500)表示500毫秒内滚动到垂直位置1000px
    • 传DOM元素:比如scrollTo(document.getElementById('target'), 800)表示滚动到目标元素的顶部位置
  3. 核心动画循环:
    内部用setTimeout递归执行g函数,每20毫秒更新一次scrollTop:

    • f是动画进度(从0到1),每次增加1/e * 20(保证总时长约为e毫秒)
    • h(f)是缓动函数的计算结果,用来控制滚动的加速度——easeInOutQuart是「先加速后减速」的缓动效果,让滚动更自然。

补全你没写完的easeInOutQuart函数

这个缓动函数的完整实现是四次方曲线,公式如下:

function easeInOutQuart(t) {
  // t是0-1之间的进度值
  return t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;
}

给你一个更易读、性能更好的简化版本

上面的代码是压缩过的,可读性差。我给你重构一个用requestAnimationFrame(比setTimeout更流畅,和浏览器刷新同步)的版本:

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

// 平滑滚动函数
function smoothScrollTo(target, duration = 500) {
  // 确定正确的滚动容器
  const scrollContainer = document.documentElement.scrollTop !== 0 
    ? document.documentElement 
    : document.body;
  const startPosition = scrollContainer.scrollTop;
  
  // 处理目标位置:支持DOM元素或数值
  const targetPosition = typeof target === 'object' 
    ? target.offsetTop 
    : Number(target);
  
  const distance = targetPosition - startPosition;
  let startTime = null;

  // 用requestAnimationFrame执行动画
  function animate(currentTime) {
    if (startTime === null) startTime = currentTime;
    const timeElapsed = currentTime - startTime;
    // 计算当前动画进度(0到1)
    const progress = Math.min(timeElapsed / duration, 1);
    // 用缓动函数计算当前滚动位置
    const currentPosition = startPosition + distance * easeInOutQuart(progress);
    
    scrollContainer.scrollTop = currentPosition;
    
    // 未完成则继续执行
    if (timeElapsed < duration) {
      requestAnimationFrame(animate);
    }
  }

  requestAnimationFrame(animate);
}

使用示例

  • 滚动到页面顶部:smoothScrollTo(0, 600)(600毫秒完成)
  • 滚动到某个DOM元素:smoothScrollTo(document.getElementById('about-section'), 800)

内容的提问来源于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 10:51:42