SVG 动画实战指南

SVG 是矢量图形的天然载体,无论放大多少倍都不会失真,且每个元素都可被 CSS 和 JavaScript 独立控制。这让 SVG 成为制作轻量、流畅动画的理想选择。相比 GIF 和视频,SVG 动画体积更小、可交互、可主题化。本文将带你掌握 SVG 动画的几种核心实现方式。

SVG 动画基础

SVG 动画主要有三种实现路径:

  • SMIL:SVG 原生的 <animate> 标签,语法直观但已被标记为废弃,不推荐新项目使用
  • CSS:通过 @keyframestransform 控制 SVG 元素,性能好、易维护,是首选方案
  • JavaScript:借助 GSAP、anime.js 等库实现复杂时间轴与路径动画,适合高级场景

日常需求中,CSS 方案覆盖了 80% 的场景,且性能最优。

CSS 动画 SVG

直接用 CSS 给 SVG 内部元素添加动画即可。下面的代码让一个圆形持续旋转:

1
2
3
4
5
6
7
8
.spinner {
animation: spin 1.2s linear infinite;
transform-origin: center;
}

@keyframes spin {
to { transform: rotate(360deg); }
}

注意 transform-origin 必须设为 center,否则旋转中心会偏移。使用 transform-box: fill-box 可确保原点作用于元素自身。

路径动画

stroke-dasharraystroke-dashoffset 是绘制「线条逐渐画出」效果的经典组合:

1
2
3
4
5
6
7
8
9
.path-draw {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s ease forwards;
}

@keyframes draw {
to { stroke-dashoffset: 0; }
}

原理是先用虚线把整条路径隐藏,再通过动画将偏移量归零,制造出笔尖沿路径移动的视觉。常用于数据图表、流程图的入场动效。

形态变化

通过改变 <path>d 属性,可以实现图形之间的平滑变形(morphing)。原生的 CSS 无法直接过渡 d,需要借助 JavaScript 库,如 flubber 或 GSAP MorphSVG:

1
2
3
// 使用 flubber 在两个路径间插值
const interpolator = flubber.interpolate(circlePath, starPath);
element.setAttribute('d', interpolator(t));

形态变化在加载动画、图标切换中表现力极强,但要注意两个路径的节点数尽量接近,过渡才会自然。

性能注意事项

SVG 动画若使用不当也会掉帧:

  • 优先 transform 与 opacity:这两个属性可由 GPU 合成,不触发重排
  • will-change 提示:对动画元素加 will-change: transform,让浏览器提前创建合成层
  • 避免 animate 属性:频繁修改 widthheightfill 会触发重绘,性能较差

实战案例

加载动画与图标动效是 SVG 最常见的用武之地。一个旋转的环形 spinner 只需几行 CSS;图标的 hover 切换则可用路径动画让线条优雅地勾勒出来。把这些微动效融入界面,能显著提升产品的精致感与反馈感,而付出的体积成本几乎可以忽略。