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

如何实现一个SVG向另一个SVG的变形过渡动画

SVG两个状态间点击变形实现方案

前提条件

两个SVG需要满足:

  • viewBox尺寸完全一致,避免变形过程中出现偏移
  • 如果使用纯CSS实现,需要两个SVG内部对应路径的节点数量完全相同,你可以在Adobe Illustrator、Figma等设计工具中调整路径节点数后重新导出

方案1:纯CSS实现(无第三方依赖)

把两个SVG的路径数据整合到同一个SVG标签内,通过CSS过渡实现变形,示例代码如下:

<!-- 整合后的SVG -->
<svg viewBox="0 0 200 200" width="200" height="200">
  <path id="morphTarget" d="这里替换为initial.svg里对应路径的d属性值" fill="#333" />
</svg>
<button id="triggerBtn">触发变形</button>

<style>
#morphTarget {
  /* 配置d属性过渡,缓入效果 */
  transition: d 1s ease-in, fill 1s ease-in;
}
/* 变形后的状态 */
#morphTarget.active {
  d: path("这里替换为final.svg里对应路径的d属性值");
  fill: #f00; /* 如果有颜色变化也可以一起过渡 */
}
</style>

<script>
const btn = document.querySelector('#triggerBtn')
const target = document.querySelector('#morphTarget')
btn.addEventListener('click', () => {
  target.classList.toggle('active')
})
</script>

如果是多路径的SVG,给每个对应路径分别配置过渡规则即可。

方案2:开源库实现(适配节点数不一致场景)

如果两个SVG路径节点数无法调整到一致,可以用专门做SVG变形的库实现,不需要手动对齐节点,示例逻辑如下:

// 引入库后获取两个路径的d值
const initialPath = "initial.svg的路径d值"
const finalPath = "final.svg的路径d值"
// 生成插值函数
const interpolate = flubber.interpolate(initialPath, finalPath, {
  ease: (t) => t * t // 实现ease-in缓动效果
})
const target = document.querySelector('#morphTarget')
const btn = document.querySelector('#triggerBtn')

btn.addEventListener('click', () => {
  let start = null
  const duration = 1000 // 动画时长1秒
  function animate(timestamp) {
    if (!start) start = timestamp
    const progress = Math.min((timestamp - start) / duration, 1)
    target.setAttribute('d', interpolate(progress))
    if (progress < 1) {
      requestAnimationFrame(animate)
    }
  }
  requestAnimationFrame(animate)
})

注意事项

  • 从XD导出SVG时建议取消“优化文件大小”相关的勾选,避免导出的路径被自动合并、简化导致节点不匹配
  • 如果是多元素组合的SVG变形,需要把两个SVG的元素一一对应,每个元素单独做变形过渡

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:27:02