创建一个SVG路径动画签名
1. 背景
https://antfu.me/posts/animated-svg-logohttps://doctorwu.me/posts/animation-signature-zhhttps://svganimation.notion.site/43aed0b2b12a423a88935ba3029fc016https://www.cnblogs.com/coco1s/p/6225973.htmlhttps://www.cnblogs.com/coco1s/p/6230165.html
其实以前有简单学习过一次 SVG 动画,但是用的没那么多,又忘记了。之前看到了 antfu 的博客,他的 logo 是个签名的线条动画,我属于一看就有思路,但是真让我动手做,又差了那么点意思。
后面又浏览到不少关于这个签名动画的实现,发现虽然核心很简单,但是还是不少人对这个挺感兴趣的。于是我也来尝试一下。
2. 原理解释
原理很简单,就是使用 SVG 的 path 属性,和 stroke-dasharray 和 stroke-dashoffset 属性,来实现动画效果。
stroke-dasharray 是用来设置虚线样式,如果设置为 100 50 ,那么就是 100 的实线,50 的空白,然后依次往下继续。 如果只有 100 ,那么就是 100 的实线,100 的空白,依次往下继续。

stroke-dashoffset 是用来设置虚线偏移量,分为正值和负值,正值是向左偏移,负值是向右偏移,当然有的还可能是顺时针逆时针方向,这个需要根据实际情况来调整,方向文档具体参考 stroke-dashoffset 。

总之,如果有一个路径长度为 100 ,而 stroke-dashoffset 为 0 ,那就是没有偏移,路径能直接显示完全。 如果 stroke-dashoffset 为 100 ,那就是向左偏移 100 ,那么路径就都隐藏掉了,一点没显示出来。 然后 stroke-dashoffset 从 100 到 0 ,那么路径就是从左 100 到 0 一点一点显示出来,动画就这样形成了。
3. 创建签名
这个签名路径我觉得比较简单了,自己触摸板绘制也行,专业一点 PS 绘制也行,看个人发挥了。 我就比较简单,跟 doctor wu 的方式一样了,在线签名 选择字体,生成一个签名,然后下载下来图片,这样签名就好了。
但是只有图片还不行,需要的是 SVG 路径,所以接下来还需要对图片处理。其实图片转 SVG 方式有很多,比如 PS 建立工作路径,然后导出 SVG 。或者直接使用在线工具,比如 convertio PNG-SVG 转换 。
我就是直接使用在线工具,下载下来 SVG 文件就行了。但是在线工具转换的,虽然效果上看还可以,但是其实还是需要再处理干净的,因为下载下来的文件,可能用到了 transform 或者 viewbox 不合理等。
这里直接使用 svgPathEditor 工具,对 SVG 路径进行编辑,将 path 粘贴进去,然后原来文件中的变形属性,这里都用上,对 path 计算后,最后提取出来。

4. 设置动画
首先获取一下 path 的长度,因为这个 path 是固定的,所以先获取一下,直接写死就好了,不用每次都查询一下。
const path = document.querySelector('path');
const pathLength = path.getTotalLength();
console.log('path 长度:', pathLength)
再将从 svgPathEditor 下载下来的 SVG 内容拷贝过来,然后给其设置一个 id ,方便下面设置动画。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="87.8 -138.886 245.9 96.89">
<path
id="signaturePath"
fill="none"
stroke="currentColor"
d="M 142.2 -134.3 c -6.2 6.2 -15 17.4 -24.8 31.2 l -7.7 11.1 l -4.6 -0.6 c -7.2 -0.9 -16.1 2.2 -16.1 5.7 c -0 0.5 3.3 0.9 7.4 0.9 c 4.1 0 7.7 0.3 7.9 0.7 c 0.3 0.5 -1.3 3.7 -3.5 7.3 c -6.9 11.1 -12.9 24.6 -13 29 c -0 3.8 1.5 7 3.3 7 c 0.4 0 5.5 -9.6 11.2 -21.4 l 10.5 -21.4 l 4.3 0.5 c 2.4 0.3 6.2 0.9 8.4 1.2 l 4 0.7 l -0.5 5.4 c -1 10.5 -0.4 20.4 1.3 23.7 c 2.1 4 2.8 4.4 7.7 4.5 c 8.3 0.1 14.9 -7.5 23.4 -27 c 2.7 -6.1 5.5 -11.2 6.2 -11.2 c 1.9 0 5.4 5 5.4 7.7 c -0 1.4 -1.3 5.8 -3 10 c -3.9 9.7 -4 15.4 -0.4 18.2 c 5.6 4.4 14.9 1.6 22.7 -6.8 c 4.1 -4.4 4.6 -4.7 5.1 -2.7 c 0.3 1.1 0.6 3.4 0.6 4.9 c -0 6.2 4 9.5 9.3 7.8 c 4.2 -1.4 11.6 -9 16.1 -16.4 l 3.5 -5.9 l 1.4 3.4 c 2.2 5.2 5 7.1 9.4 6.6 c 2.1 -0.3 4.6 -0.8 5.6 -1.2 c 1.4 -0.7 1.7 -0.3 1.7 2.2 c -0 11.2 12 13.8 22.6 4.9 l 3.1 -2.6 l -0.4 2.3 c -0.4 1.9 0.1 2.5 2.8 3.5 c 1.8 0.6 3.3 1 3.4 0.9 c 0.1 -0.2 2.9 -4.6 6.3 -9.8 c 9.1 -14.1 17.1 -21.1 22.3 -19.5 c 2.9 0.9 3.4 5.2 1.6 12.5 c -2.3 8.6 -2.2 12.5 0.3 15 c 2.4 2.4 8.8 2.7 12.9 0.6 c 6 -3.1 15.8 -17.3 13.5 -19.6 c -0.7 -0.7 -1.7 0.3 -3.4 3.2 c -9.9 18 -21.9 19.4 -15 1.8 c 4.6 -11.6 1.5 -21.6 -6.7 -21.4 c -6.5 0.2 -12.9 4.7 -20.6 14.4 c -1.7 2.1 -2.6 2.7 -2.2 1.5 c 0.4 -1.1 0.9 -4.6 1.2 -7.8 l 0.6 -5.7 l -3.5 -0 c -4.3 -0 -5.3 1.2 -6.2 6.8 c -1 6.6 -4.5 13.1 -10.1 19 c -4.3 4.3 -5.7 5.2 -8.6 5.2 c -4.7 -0 -5.9 -1.5 -5.9 -7.2 c 0 -3.9 1.1 -7 6.1 -16.7 c 3.7 -7.1 5.9 -12.5 5.6 -13.5 c -1 -2.5 -5 -1.9 -7.9 1.1 c -2.7 2.8 -9.8 16.7 -9.8 19 c -0 0.7 -1.4 2.8 -3.1 4.8 c -3.4 3.8 -6.7 4.5 -9.3 1.9 c -2.3 -2.2 -2.1 -11.8 0.4 -17.3 c 3.1 -6.7 2.2 -10.1 -2.6 -10.1 c -3.1 -0 -4.5 2.1 -5.3 8.2 c -1.4 10.4 -15.1 31.5 -19.8 30.6 c -1.6 -0.3 -1.8 -1.6 -1.9 -13.3 c -0.1 -16.5 0.1 -15.5 -3.3 -15.5 c -3.3 -0 -4.1 1.4 -4.1 7.3 c -0.1 5 -1.2 7.3 -6.5 12.8 c -6.8 7.2 -12.7 9.7 -15.4 6.6 c -1.2 -1.5 -0.6 -3.9 2.8 -12.5 c 1.1 -2.9 2.1 -7.4 2.1 -10 c 0 -4.4 -0.3 -4.9 -5.9 -10.2 c -5.1 -4.7 -5.9 -5.9 -5.4 -8.2 c 0.8 -4.1 -0.2 -6.1 -2.5 -4.9 c -2.5 1.3 -4.6 6.5 -3.8 9.4 c 1.2 4.8 -10.3 28.5 -16.5 34.2 c -4.4 4 -5.1 4.1 -7.3 1.9 c -1.7 -1.7 -2 -3.9 -1.7 -12.4 c 0.6 -14.5 9.6 -50.1 15.8 -62.3 l 2.4 -4.8 l -2.3 -1.9 c -3.7 -3.1 -6.4 -2.5 -11.6 2.7 z m -3.8 22.3 c -3 9.1 -5.8 18.4 -6.4 20.6 l -1 4.2 l -6.3 -1.6 c -3.4 -0.8 -6.6 -1.8 -7 -2.2 c -0.9 -0.8 5.8 -12.5 13.2 -23 c 4.4 -6.3 12.1 -15.3 12.6 -14.8 c 0.2 0.2 -2.1 7.7 -5.1 16.8 z"
/>
</svg>
最后设置动画,按照上面的思路,将 pathLength 的值给 stroke-dashoffset 。 完整代码:
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="87.8 -138.886 245.9 96.89"
>
<path
id="signaturePath"
fill="none"
stroke="currentColor"
d="M 142.2 -134.3 c -6.2 6.2 -15 17.4 -24.8 31.2 l -7.7 11.1 l -4.6 -0.6 c -7.2 -0.9 -16.1 2.2 -16.1 5.7 c -0 0.5 3.3 0.9 7.4 0.9 c 4.1 0 7.7 0.3 7.9 0.7 c 0.3 0.5 -1.3 3.7 -3.5 7.3 c -6.9 11.1 -12.9 24.6 -13 29 c -0 3.8 1.5 7 3.3 7 c 0.4 0 5.5 -9.6 11.2 -21.4 l 10.5 -21.4 l 4.3 0.5 c 2.4 0.3 6.2 0.9 8.4 1.2 l 4 0.7 l -0.5 5.4 c -1 10.5 -0.4 20.4 1.3 23.7 c 2.1 4 2.8 4.4 7.7 4.5 c 8.3 0.1 14.9 -7.5 23.4 -27 c 2.7 -6.1 5.5 -11.2 6.2 -11.2 c 1.9 0 5.4 5 5.4 7.7 c -0 1.4 -1.3 5.8 -3 10 c -3.9 9.7 -4 15.4 -0.4 18.2 c 5.6 4.4 14.9 1.6 22.7 -6.8 c 4.1 -4.4 4.6 -4.7 5.1 -2.7 c 0.3 1.1 0.6 3.4 0.6 4.9 c -0 6.2 4 9.5 9.3 7.8 c 4.2 -1.4 11.6 -9 16.1 -16.4 l 3.5 -5.9 l 1.4 3.4 c 2.2 5.2 5 7.1 9.4 6.6 c 2.1 -0.3 4.6 -0.8 5.6 -1.2 c 1.4 -0.7 1.7 -0.3 1.7 2.2 c -0 11.2 12 13.8 22.6 4.9 l 3.1 -2.6 l -0.4 2.3 c -0.4 1.9 0.1 2.5 2.8 3.5 c 1.8 0.6 3.3 1 3.4 0.9 c 0.1 -0.2 2.9 -4.6 6.3 -9.8 c 9.1 -14.1 17.1 -21.1 22.3 -19.5 c 2.9 0.9 3.4 5.2 1.6 12.5 c -2.3 8.6 -2.2 12.5 0.3 15 c 2.4 2.4 8.8 2.7 12.9 0.6 c 6 -3.1 15.8 -17.3 13.5 -19.6 c -0.7 -0.7 -1.7 0.3 -3.4 3.2 c -9.9 18 -21.9 19.4 -15 1.8 c 4.6 -11.6 1.5 -21.6 -6.7 -21.4 c -6.5 0.2 -12.9 4.7 -20.6 14.4 c -1.7 2.1 -2.6 2.7 -2.2 1.5 c 0.4 -1.1 0.9 -4.6 1.2 -7.8 l 0.6 -5.7 l -3.5 -0 c -4.3 -0 -5.3 1.2 -6.2 6.8 c -1 6.6 -4.5 13.1 -10.1 19 c -4.3 4.3 -5.7 5.2 -8.6 5.2 c -4.7 -0 -5.9 -1.5 -5.9 -7.2 c 0 -3.9 1.1 -7 6.1 -16.7 c 3.7 -7.1 5.9 -12.5 5.6 -13.5 c -1 -2.5 -5 -1.9 -7.9 1.1 c -2.7 2.8 -9.8 16.7 -9.8 19 c -0 0.7 -1.4 2.8 -3.1 4.8 c -3.4 3.8 -6.7 4.5 -9.3 1.9 c -2.3 -2.2 -2.1 -11.8 0.4 -17.3 c 3.1 -6.7 2.2 -10.1 -2.6 -10.1 c -3.1 -0 -4.5 2.1 -5.3 8.2 c -1.4 10.4 -15.1 31.5 -19.8 30.6 c -1.6 -0.3 -1.8 -1.6 -1.9 -13.3 c -0.1 -16.5 0.1 -15.5 -3.3 -15.5 c -3.3 -0 -4.1 1.4 -4.1 7.3 c -0.1 5 -1.2 7.3 -6.5 12.8 c -6.8 7.2 -12.7 9.7 -15.4 6.6 c -1.2 -1.5 -0.6 -3.9 2.8 -12.5 c 1.1 -2.9 2.1 -7.4 2.1 -10 c 0 -4.4 -0.3 -4.9 -5.9 -10.2 c -5.1 -4.7 -5.9 -5.9 -5.4 -8.2 c 0.8 -4.1 -0.2 -6.1 -2.5 -4.9 c -2.5 1.3 -4.6 6.5 -3.8 9.4 c 1.2 4.8 -10.3 28.5 -16.5 34.2 c -4.4 4 -5.1 4.1 -7.3 1.9 c -1.7 -1.7 -2 -3.9 -1.7 -12.4 c 0.6 -14.5 9.6 -50.1 15.8 -62.3 l 2.4 -4.8 l -2.3 -1.9 c -3.7 -3.1 -6.4 -2.5 -11.6 2.7 z m -3.8 22.3 c -3 9.1 -5.8 18.4 -6.4 20.6 l -1 4.2 l -6.3 -1.6 c -3.4 -0.8 -6.6 -1.8 -7 -2.2 c -0.9 -0.8 5.8 -12.5 13.2 -23 c 4.4 -6.3 12.1 -15.3 12.6 -14.8 c 0.2 0.2 -2.1 7.7 -5.1 16.8 z"
/>
</svg>
</template>
<style>
#signaturePath {
stroke-dasharray: 1315.3;
stroke-dashoffset: 1315.3;
fill: transparent;
animation: drawSignature 8s linear infinite;
}
@keyframes drawSignature {
0% {
stroke-dashoffset: 1315.3;
}
15% {
fill: transparent;
}
35%,
75% {
stroke-dashoffset: 0;
fill: currentColor;
}
90%,
100% {
stroke-dashoffset: 1315.3;
fill: transparent;
}
}
</style>