跳到主要内容

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" 结束后计算样式还在;要进文件就在 finishedsetAttribute("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