CSS与WAAPI
应用内 inline SVG 的动画首选 CSS Transitions / Animations 或 Web Animations API。它们和页面其它 UI 共用时间线、可取消、可查 playState,不必在文档里嵌一套 SMIL 时间图。
SMIL 仍然可用,但岗位不在这里,见 SMIL 与属性动画。
1. 适用 / 不适用
适用: 选中反馈、手柄、图例高亮、小幅位移动画、opacity / fill / stroke / transform。节点数在「还能当 DOM」的量级。
不适用: 每帧改几千个几何点;路径 morph 当生产通道;依赖 cx / r / d 的 CSS 动画还要三引擎像素级一致。后者见 差异清单。
2. 只动 transform,几何留给文档
属性 cx / r / d 是文档几何。CSS 里它们在 部分引擎 已是几何属性,可以插值;另一些引擎只认 XML 属性,或 CSS 必须带单位。生产默认:
- 位移、旋转、缩放 → CSS / WAAPI 的
transform - 必须改半径、改 path → JS 写 attribute,或自包含文件用 SMIL
- 不要 attribute 一份、
style.cx一份还当同一 source of truth
export function pulseNode(el: SVGGraphicsElement): Animation {
el.style.transformBox = "fill-box";
el.style.transformOrigin = "center";
return el.animate(
[
{ transform: "translate(0px, 0px) scale(1)" },
{ transform: "translate(0px, 0px) scale(1.06)" },
],
{
duration: 220,
easing: "cubic-bezier(0.2, 0.8, 0.2, 1)",
fill: "forwards",
direction: "alternate",
iterations: 2,
},
);
}
transform-box / transform-origin 必须写明。SVG 上 origin 默认曾经是 0 0,后来向 HTML 的 50% 50% 靠;再叠加 fill-box | stroke-box | view-box,不写就等于把锚点交给引擎历史包袱。Illustrator 导出的图形往往假设绕用户空间原点转。详见 用户坐标系与变换。
几何属性若确认目标引擎可 CSS,可以动 r,但仍要单位:
export function growRadius(circle: SVGCircleElement, toPx: number): Animation {
return circle.animate(
[{ r: "8px" }, { r: `${toPx}px` }],
{ duration: 300, easing: "ease-out", fill: "forwards" },
);
}
这在 Chromium / Gecko 上常见可用;不要假设 d 也能这样补间。可移植路径动画走 描边与 getPointAtLength。
3. WAAPI 管生命周期,不要平行再开一条 rAF
export function moveBy(
el: SVGGraphicsElement,
dx: number,
dy: number,
ms: number,
): Animation {
el.style.transformBox = "fill-box";
el.style.transformOrigin = "0 0";
const animation = el.animate(
[
{ transform: "translate(0px, 0px)" },
{ transform: `translate(${dx}px, ${dy}px)` },
],
{ duration: ms, fill: "forwards", easing: "ease-out" },
);
return animation;
}
暂停、seek、打断用 animation.pause() / currentTime / cancel()。不要 CSS 动画还在播,同时又用 rAF 改同一 transform。需要跟指针走的预览,用 rAF 写 预览层,松手再提交一条 WAAPI 或写回 matrix,见 相机。
fill: "forwards" 结束后计算样式还在;要进文件就在 finished 里 setAttribute("transform", ...) 并清 style.transform,否则序列化丢动画、屏幕上还留着。
4. will-change 慎用
will-change: transform 会促使引擎提升合成层。SVG 上常见后果是 按当前尺寸光栅一块,随后改 viewBox / 放大窗口,这一块发糊,比没提升还糟。滤镜同理,见 滤镜合成层。
规则:只在即将开播的节点上加,finished 后去掉;禁止在容器 <svg> 或每一棵图标上常驻。
5. 失败形态
| 症状 | 原因 |
|---|---|
| 旋转绕左上角或乱飞 | 未设 transform-box / transform-origin |
Chrome 能动 r,Safari 不动 | 把几何属性 CSS 当可移植通道 |
| 导出后位置还原 | forwards 只留在 computed style,没写回 attribute |
| 放大后动画节点发糊 | will-change 或 filter 造成离屏位图 |
| 拖拽时抖动 | WAAPI 与指针 rAF 同时写 transform |
权威资料
核对日期:2026-08-26