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

如何流畅实现SVG中animateTransform旋转速度的动态调整?

实现SVG图形平滑减速旋转

直接修改SVG动画的dur属性会导致动画跳帧,因为动画会重置状态重新计算,所以没法实现平滑过渡。要达成「初始快速旋转,4秒内逐渐停止」的效果,给你两种靠谱方案:

方案一:纯SVG关键帧动画

利用animateTransform的values和keyTimes属性,定义不同阶段的旋转节奏,前1秒快速转,后3秒逐步减慢直到停止,总时长刚好4秒。

<svg viewBox='0 0 200 200' style='width:400px;'>
  <g transform="translate(100,100)" stroke="#000" stroke-width="2">
    <path d="M0 0-70 70A99 99 0 0 1-70-70Z" fill="#f00"/>
    <path d="M0 0-70-70A99 99 0 0 1 70-70Z" fill="#080"/>
    <path d="M0 0 70-70A99 99 0 0 1 70 70Z" fill="#dd0"/>
    <path d="M0 0 70 70A99 99 0 0 1-70 70Z" fill="#04e"/>
  </g>

  <animateTransform
    attributeName="transform"
    attributeType="XML"
    type="rotate"
    values="0 0 0; 360 0 0; 720 0 0; 900 0 0; 990 0 0; 1080 0 0"
    keyTimes="0; 0.25; 0.5; 0.7; 0.85; 1"
    dur="4s"
    fill="freeze"
    id='rad_rotate' />
</svg>

细节说明:

  • values里的数值是旋转角度关键节点:前0.25秒(1秒)转1圈,之后每段旋转量逐步减少,最终总共转3圈后停下
  • keyTimes对应每个关键帧的时间占比,0是动画开始,1是4秒结束
  • fill="freeze"让动画结束后保持最后静止状态

方案二:JavaScript实时控制(更灵活)

用requestAnimationFrame逐帧计算旋转角度,通过减速公式实现平滑减速,完全避开修改SVG动画属性导致的跳变问题。

<svg viewBox='0 0 200 200' style='width:400px;'>
  <g id="rotating-group" transform="translate(100,100) rotate(0)" stroke="#000" stroke-width="2">
    <path d="M0 0-70 70A99 99 0 0 1-70-70Z" fill="#f00"/>
    <path d="M0 0-70-70A99 99 0 0 1 70-70Z" fill="#080"/>
    <path d="M0 0 70-70A99 99 0 0 1 70 70Z" fill="#dd0"/>
    <path d="M0 0 70 70A99 99 0 0 1-70 70Z" fill="#04e"/>
  </g>
</svg>

<script>
const rotatingGroup = document.getElementById('rotating-group');
let currentAngle = 0;
// 初始角速度:每秒转1圈(360度)
let angularSpeed = 360;
// 4秒减速到0,计算每帧减速幅度
const deceleration = angularSpeed / 4 / 60;
let startTime = null;

function animate(timestamp) {
  if (!startTime) startTime = timestamp;
  const elapsed = (timestamp - startTime) / 1000;

  // 角速度减到0就不再变化
  if (angularSpeed > 0) {
    angularSpeed = Math.max(0, angularSpeed - deceleration);
  }

  // 更新当前旋转角度
  currentAngle += angularSpeed / 60;
  rotatingGroup.setAttribute('transform', `translate(100,100) rotate(${currentAngle})`);

  // 角速度不为0就继续动画
  if (angularSpeed > 0) {
    requestAnimationFrame(animate);
  }
}

// 启动动画
requestAnimationFrame(animate);
</script>

细节说明:

  • 直接操作旋转组的transform属性,逐帧更新角度,完全避免SVG动画的状态重置问题
  • 这里用的是线性减速,如果你想要更自然的「先快后慢」效果,可以把减速逻辑改成指数形式,比如每帧让角速度乘以0.98:angularSpeed *= 0.98

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:37:04