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

rAF如何实现等价CSS动画alternate方向与无限迭代效果

实现方案

你现在的代码缺三个核心逻辑,补上之后就能和CSS动画效果完全一致:

  • 无限循环逻辑:不要在进度到1的时候终止rAF,用时间取模计算当前所属的动画周期
  • 交替方向判断:区分正向(路径起点到终点)、反向(路径终点回起点)两个阶段的进度
  • ease-in-out缓动匹配:当前代码的进度是线性增长的,和CSS动画的缓动节奏不匹配,需要给进度套对应缓动函数

具体实现步骤

  1. 首先定义时间参数:单趟动画时长和CSS保持一致为3000ms,一个完整往返周期就是6000ms
  2. 每帧执行时,先计算从动画启动到当前的总耗时,对周期时长取模,拿到当前周期内的已走时间,实现无限循环效果
  3. 判断当前是正向还是反向阶段:
    • 周期内时间小于3000ms时为正向,线性进度 = 周期内时间 / 单趟时长
    • 周期内时间大于等于3000ms时为反向,线性进度 = 1 - (周期内时间 - 单趟时长)/单趟时长
  4. 把线性进度传入ease-in-out缓动函数,得到最终的路径进度,再计算对应坐标更新圆点位置即可

CSS的ease-in-out对应三次贝塞尔曲线cubic-bezier(0.42, 0, 0.58, 1),可以直接用JS实现对应的计算函数,视觉效果和原生CSS完全一致。


完整可运行代码

const singleDuration = 3000; // 单趟动画时长,和CSS配置对齐
const cycleDuration = singleDuration * 2; // 往返一次的完整周期时长
const curve = document.querySelector('#curve');
const totalPathLength = curve.getTotalLength();
const dot = document.querySelector('#dot');
const animationStart = performance.now();

// 实现CSS ease-in-out 缓动
function easeInOut(t) {
  return t < 0.5
    ? 4 * t * t * t
    : 1 - Math.pow(-2 * t + 2, 3) / 2;
}

function animate() {
  const totalElapsed = performance.now() - animationStart;
  // 取模实现无限循环,拿到当前周期内的耗时
  const currentCycleTime = totalElapsed % cycleDuration;
  let linearProgress;

  if (currentCycleTime < singleDuration) {
    // 正向阶段:从起点移动到终点
    linearProgress = currentCycleTime / singleDuration;
  } else {
    // 反向阶段:从终点移动回起点
    linearProgress = 1 - (currentCycleTime - singleDuration) / singleDuration;
  }

  // 应用缓动得到最终路径进度
  const pathProgress = easeInOut(linearProgress);
  // 计算当前点坐标更新位置
  const point = curve.getPointAtLength(pathProgress * totalPathLength);
  dot.setAttribute("transform", `translate(${point.x}, ${point.y})`);

  requestAnimationFrame(animate);
}

animate();

如果需要和浏览器原生CSS动画的缓动做到像素级完全一致,也可以借助Web Animations API直接读取动画进度,不需要手写缓动逻辑,日常场景下上面的实现已经可以做到视觉无差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:21:35