SVG 描边:让线条自己画出来
最经典的 SVG 动画只动一个数。把一条路径的虚线段长设成它自身的总长,整条线就成了「一段实线加一段等长空白」;再让虚线偏移 stroke-dashoffset 从总长滑到 0,实线段便像被一只笔逐渐推出来。签名重放、对号打勾、loading 圈都是这一招。
其中
是 getTotalLength() 给出的总长,
是引擎插出来的进度。
1 · 描边自绘
2 · 为什么是 1 减进度
dashoffset 把虚线图案沿路径整体平移。偏移等于总长时,那唯一的实线段恰好被平移到路径起点之前,屏幕上什么都看不到;偏移归 0 时实线段回到原位、完整显现。所以进度
对应偏移
,中间任意时刻露出的正是前
那一段。
警示 · dasharray 必须恰好等于该路径自身的总长,不能取一个「足够大的数」凑。虚线图案是「实线段 + 空白段」循环平铺的,段长小于总长时后面会露出第二段实线;段长大于总长时前几帧的偏移落在图案的空白区里,起笔会延迟。三条子路径各有各的长度,所以要各设各的
dasharray,不能共用一个值。
3 · 顺序绘制的轴是长度
三笔依次画出,用的不是三个错开的动画,而是把各子路径按长度首尾接成一条总长轴,用同一个全局进度去点亮:第 笔的局部进度是 ,其中 是它在这条轴上的起点。
这与交错同源,只是那里的轴是时间、每个单位一个延迟,而本页的轴是路径长度——长笔自然占用更多进度,短笔一闪而过,节奏由几何决定而非人为指定。
const path = svg.querySelector('path');
const L = path.getTotalLength();
path.style.strokeDasharray = L;
new Animation({
keyframes: [0, 1],
duration: 2000,
ease: 'easeInOut',
onUpdate: (g) => {
path.style.strokeDashoffset = L * (1 - g);
},
});
描边动的是笔触本身;让一个物体沿这条路径行进并朝向前进方向,见沿路径运动。进度本身只是一次普通的插值,被缓动塑形后接到 dashoffset 上。