SVG描边动画核心是stroke-dasharray与stroke-dashoffset配合CSS动画,需先用getTotalLength()获取真实路径长度,设为L,L和初始offset=L,再通过transition或@keyframes将offset减至0实现绘制效果。

SVG stroke-dasharray 和 stroke-dashoffset 是描边动画的核心
纯 CSS 实现 SVG 路径描边动画,不依赖 JS,关键就靠这两个属性配合 transition 或 @keyframes。它们不是“画笔移动”,而是用虚线“遮罩+位移”制造绘制错觉。
原理很简单:stroke-dasharray 设定虚线长度(如 10,5),但对单条路径最常用的是设成 总路径长度, 总路径长度——相当于一条实线被“全挡住”;stroke-dashoffset 控制这条虚线的起始偏移。把 offset 从「总长度」减到 0,虚线就“露出来”了,看起来像在绘制。
所以第一步永远是:先拿到路径的精确长度。
- 用 JS 调用
pathEl.getTotalLength()获取真实长度(注意:必须等 SVG 渲染完成后再调,否则返回 0) - 或用开发者工具选中
<path>,在控制台手动执行$0.getTotalLength() - 别手算 d 属性、别抄网上随便写的 100/200 —— 错了动画就卡在半路
用 @keyframes 做一次性的绘制动画
适合图标入场、加载指示器这类“播完即停”的场景。关键点是:初始 stroke-dashoffset 设为总长度,结束时设为 0,并确保 stroke-dasharray 固定为 L,L(L 是你测出的真实长度)。
立即学习“前端免费学习笔记(深入)”;
svg path {
stroke-dasharray: 248, 248; /* 替换为你自己的 L */
stroke-dashoffset: 248;
transition: stroke-dashoffset 0.6s ease-out;
}
svg path.drawn {
stroke-dashoffset: 0;
}触发只需加 class:pathEl.classList.add('drawn')。注意:不要只写 transition 却忘了初始态的 stroke-dashoffset,否则动画不启动。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 动画时间越长,用户感知越“稳”,但超过 1s 易显拖沓;0.4–0.8s 是较安全区间
-
ease-out比linear更自然,模拟手绘收尾减速 - 如果路径含
fill,记得先设fill: none,否则描边动画会被填充遮住
CSS transition 无法重播?用 animation + forwards 更可控
直接操作 class 的 transition 方案有个硬伤:class 移除后动画会倒放。想“播放一次、停在终点、下次再点又重播”,得用 @keyframes 配合 animation-fill-mode: forwards。
@keyframes draw {
from { stroke-dashoffset: 248; }
to { stroke-dashoffset: 0; }
}
svg path {
stroke-dasharray: 248, 248;
stroke-dashoffset: 248;
animation: draw 0.7s ease-out forwards;
}这样动画播完自动停留在 stroke-dashoffset: 0,再 JS 触发 el.style.animation = 'none'; el.offsetHeight; el.style.animation = ''; 就能强制重播——这是绕过浏览器缓存动画状态的常用技巧。
- 别漏写
forwards,否则动画一结束就跳回初始态 - 重播时仅改
animation值不够,必须触发重排(offsetHeight是最轻量的方式) - 若路径是
<polyline>或<rect>,同样适用,但getTotalLength()仍要调用对应元素方法
响应式 SVG 下长度变化导致动画错乱怎么办
当 SVG 设置了 width="100%" 或用 CSS 缩放时,getTotalLength() 返回的是原始坐标系下的长度,而渲染后的路径实际长度已变——动画就会快进、卡顿甚至不触发。
根本解法只有一个:让 SVG 不缩放,用 viewBox 控制缩放行为,所有尺寸用相对单位。
- 删掉
width/height属性,只留viewBox="0 0 100 100"(按设计稿比例设) - 用 CSS 控制容器宽高,SVG 自动等比拉伸,
getTotalLength()依然准确 - 如果必须用
<img src="icon.svg">,那 JS 无法访问内部 path,这种方案直接不可行——换为内联 SVG
真正容易被忽略的是:动画逻辑和响应式布局是两套系统,强行混用只会让 dashoffset 值失去物理意义。先保长度准,再谈动效顺。


















