SVG 签名动画初探
发现 Anthony Fu 写的这篇 Animated SVG Logo,可以通过 SVG 和 CSS 动画实现动态的签名效果;后来又看到了 Innei/Shiro 主题用了这样的签名效果来在版权卡片上面签名,感觉很有意思,于是自己把两者结合,用 Anthony 的方法制作了图标,实现了 Innei 中图标的功能……
这篇文章是个简单的教程/记录,希望能帮助到你。
目前你可以在本站每篇文章尾部的 Copyright 卡片上看到这个动态签名。
Tip
如果你正在 RSS 阅读器中阅读这篇文章,可能无法看到上面图标的动态效果(甚至只能看见一片白),建议在浏览器中查看。
原理简析
假设现在我们有一个“一笔画成”的 SVG 文件,我们可以通过控制这“一笔”显示的部分有多长来实现动画效果,而 CSS 的 stroke-dasharray
属性正好可以做到这一点。
但是,很多名字是不能“一笔画成”的,这也是不少人放弃这个方法的原因,但是从 Anthony 的文章中我们得到一个新方法:使用一个遮罩来遮住多余的部分。他在文中使用这个方法是为了笔画的粗细变化,但是只要把遮罩的形状设置得合适,我们也可以用这个方法来实现“一笔画成”的效果。
更具体的细节,可以前往 Anthony 的文章 查看。
至于 Innei/Shiro 主题中的效果,其实并不像签名,而是“逐渐显示”。 这个制作起来会方便很多,如果你只想要一个简单的动画效果,而不是一定要“签名”动画,可以查看制作一个好看的动态签名🖋️ - 柃夏chapu。
实现步骤
画图标
- 在 Google Fonts 中选一个自己喜欢的字体;
- 在 https://danmarshall.github.io/google-font-to-svg-path/ 中下载为 SVG 文件
- 将 SVG 文件导入 Figma
- 用钢笔工具跟着线路“一笔画”画出签名(中间不连续的地方可以先直接连上,比如下图 i 的竖杠和圆点之间)
Tip
这步应该是最难最烦的,尤其是对于不熟悉 Figma 的人,可以自行搜索怎么用 Figma 的钢笔工具
也可以尝试把我画好的签名导入 Figma,看一看是怎么操作的。 - 画一个可以遮住多余部分的图形(如果需要)
- 将遮挡图形设置为 Mask
- 想要线条粗细变化?方法是加遮罩,和上文提到的遮住多余部分一个道理,把粗的线遮细点……
- 导出这个 SVG 文件
放入项目
-
导入你的项目中,不同框架导入方式不同,比如我用 Astro,可以这样:
// signature.astro --- import Sign from "@assets/signature-yunfi.svg?raw"; --- <div class="float-right signature-wrapper"> <Fragment set:html={Sign} /> </div>
-
设置 CSS,可以参考 antfu 文章中的写法
- 最好去 SVG 文件里给主要的 path 加上 id(我加的是
main-stroke
),方便 CSS 进行 query --signature-length
属性是主要笔画的长度,最好通过二分法试一试,如何太大,动画看上去会很快,如果太小动画会从笔画上的好几个地方一起开始播放。
/* 使用了带有 nested 支持的 Tailwind CSS,如果你没用的话,需要自己写 */ .signature-wrapper { --signature-length: 2550px; } /* https://antfu.me/posts/animated-svg-logo */ .signature-wrapper #main-stroke { @apply stroke-black dark:stroke-white opacity-100; stroke-dashoffset: 1px; stroke-dasharray: var(--signature-length) 0; animation: grow 7s ease-out forwards infinite; transform-origin: center; animation-delay: 0s; } @media (prefers-reduced-motion) { path { animation: none !important; stroke-dasharray: unset !important; } } @keyframes grow { 0% { stroke-dashoffset: 1px; stroke-dasharray: 0 var(--signature-length); opacity: 0; } 10% { opacity: 1; } 45% { stroke-dasharray: var(--signature-length) 0; } /* Moving back */ 65% { stroke-dasharray: var(--signature-length) 0; } 95%, to { stroke-dasharray: 0 var(--signature-length); } }
- 最好去 SVG 文件里给主要的 path 加上 id(我加的是
-
大功告成!