今天的主题:动画 SVG Logo 👆
这个主题来源于 antfu(托尼) 的一篇文章:Animated SVG Logo。
文中托尼大佬已经讲得很清楚了。所以我在这进行补充基础知识和实操记录。
SVG #
SVG 是一种图片格式,矢量图。它跟其他图片格式的区别就在于:它可以无限放大,不会失真、丢失细节。
我们在 VSCode 编辑器中打开 SVG ,它不像 PNG、JPG 那样打开后直接是图片,而是一堆看不懂的乱码?(是 XML 格式的编码)
👇 左边是 PNG ,右边是 SVG 。
如果你要看 SVG 呈现图片模样,可以用浏览器打开,或者用一些查看图片的软件。
SVG 的编码格式是 XML ,我们先从 XML 讲起吧。👇
XML #
- XML 和 HTML 很像,都是尖括号的标签。
- HTML 的标签都是有专门的作用,例如 a 标签是链接,h 标签是标题,img 标签是图片。而 XML 是没有特定规定的,你想怎样安排都可以,例如 👇
<title date="2023-08-24">介绍xml</title>
<author>xxx</author>
<date>2023-08-24</date>
<yyyy>2023</yyyy>
<mm>08</mm>
<dd>24</dd>
是的,尖括号里英文你可以自己写,你可以自定义标签,也可以自定义属性。xml 就是这么简单!互联网早期还用 xml 这个格式来传送/交换数据。现在改用 JSON 了。
你可以理解 HTML SVG 都是 XML 一种设定好的规则。
简单讲完 XML ,回到 SVG 。我们来看看 SVG 规定了哪些规则!👇
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="#999"
stroke-width="10" fill="#222" />
</svg>
最外层 <svg>
和 <html>
一样包裹着其他标签。
里面的标签和属性就是画图用的规则了,像上面用到的 <circle>
标签就是用来规定画一个怎么样的圆。
- cx 和 cy 是圆心坐标
- r 是半径
- stroke 是画笔颜色
- stroke-width 是画笔粗细
- fill 是填充这个圆的颜色
你可以把以上代码复制到一个后缀为 .svg
的文件里。然后用浏览器打开,就可以看到如下图案。
如果只是画圆圈,那还是比较简单的。但是如果要画精细一点的图案,难度不亚于用 0 和 1 写电脑程序…
- 所以我们不可能真的用 SVG 来画图,只是稍微了解一下它的原理,以便后续操控它。
- 我们应该用其他软件来画图,比如 Figma ,然后导出成 SVG 。
刚刚上面介绍的是用 SVG 画圆的一些标签和属性的规则。
接下来我们直奔主题,我们本次制作这个会动的 SVG 需要用到的是 SVG 路径!
是的!SVG 除了可以画圆,还可以画正方形、长方形、三角形、乱七八糟形。最重要的是今天的主角:路径,你可以理解为“一条线”
要了解更多 SVG 的画图规则,可以看看我写的小黄鸭:SVG | 小黄鸭
SVG 路径 - path #
我们先来看看 SVG 画路径是怎么样的吧 👇
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M150 0 L75 200 L225 200 Z" />
</svg>
这个 <path>
标签,就是【路径】,里面的字母和数字也是有规则的 👇
每一个字母代表着一种操作:
- M 代表移动画笔到某个位置
- L 代表画一条直线到某个位置
… 这里就不过多介绍,毕竟我们不打算用 SVG 画图。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M150 0 L75 200 L225 200 Z"
stroke='red' stroke-width='2' fill='none'/>
</svg>
我们同样可以使用 stroke
和 stroke-width
来规定画笔的颜色和粗细。
我们现在通过 Figma 来画一个图吧 👇
这里简单的用钢笔工具勾勒了一个 关于我的符号(戈),👆 你可以点击右下角的【Export】导出 SVG 图片 或者点击右上角切换模块就可以看到 SVG 的格式了 👇
它的 SVG 格式如下 👇
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="103" viewBox="0 0 115 103" fill="none">
<path d="M3 46C66 27 35.5 -2 20.5 5.08248C-6.70896 17.9296 48.5 84.8205 80.5 69.5825C104.5 55.5 83 22.5825 56 36.5825C25 54 27.5 97.9226 69 99.5051C102 98.5 112 72 112 72" stroke="white" stroke-width="6" stroke-linecap="round"/>
</svg>
为了适配暗黑模式可以 👇
<svg ma xmlns="http://www.w3.org/2000/svg" width="115" height="103" viewBox="0 0 115 103" fill="none">
<style>
path {
stroke: #eee;
}
@media (prefers-color-scheme: dark) {
path {
stroke: #222;
}
}
</style>
<path d="M3 46C66 27 35.5 -2 20.5 5.08248C-6.70896 17.9296 48.5 84.8205 80.5 69.5825C104.5 55.5 83 22.5825 56 36.5825C25 54 27.5 97.9226 69 99.5051C102 98.5 112 72 112 72" stroke-width="6" stroke-linecap="round"/>
</svg>
图片我们已经导出来了。但是应该如何动起来呢?
现在这个 SVG 图片是静止不动的,不过好在我们前面了解了一点关于 XML 和 SVG 的基础知识。我们知道 XML 是类似 HTML 的东西,所以我们也可以使用 CSS 也就是 <style>
标签来制作动画的。
我们先把 SVG 导入到一个 index.html
文件里,然后来了解更多关于路径的知识吧
SVG 路径 - 虚线 #
虚线:stroke-dasharray #
我们在之前的(戈)svg 图片里加入虚线👇
<style>
/* 修改 `<path>` 标签的 CSS */
path {
stroke-dasharray: 10px 10px;
//参数1:虚线长度,参数2:虚线间隙
}
</style>
矢量位移:stroke-dashoffset #
path {
stroke-dasharray: 10px 10px;
stroke-dashoffset: 10px;
}
你可以把 stroke-dashoffset
的值依此修改成 20px、30px、40px
你就会发现这条线在“走”
因此我们就可以用 css 来做动画 👇
如果你不了解 CSS 动画,可以看我的小黄鸭教程: CSS 动画 | 小黄鸭
path {
stroke-dashoffset: 0px;
stroke-dasharray: 10px 10px;
animation: grow 4s infinite;
}
@keyframes grow {
0% {
stroke-dashoffset: 0px;
}
50% {
stroke-dashoffset: 100px;
}
to {
stroke-dashoffset: 0px;
}
}
我们利用 css 的动画改变 stroke-dashoffset
,它的虚线长度、虚线的间隔不变,只有矢量在动。
我们换个思路,改变虚线的长度!让间隔尽可能的长,这样在 SVG 这个区域内就只有一段虚线!而且是可以变长变短的虚线!
<svg
xmlns="http://www.w3.org/2000/svg"
width="645"
height="383"
viewBox="0 0 645 383"
fill="none">
<path
d="M5 377.855C293 203.455 427 38.8546 285 8.85462C143 -21.1454 -122 131.855 78 194.855C132 211.865 378 263.855 640 126.855"
stroke="white"
stroke-width="10"
stroke-linecap="round" />
</svg>
<style>
path {
stroke-dashoffset: 1px;
stroke-dasharray: 100px 1000px;
animation: grow 4s ease forwards infinite;
}
@keyframes grow {
0% {
stroke-dasharray: 0 500px;
opacity: 0;
}
10% {
opacity: 1;
}
40% {
stroke-dasharray: 500px 0;
}
75% {
stroke-dasharray: 500px 0;
}
95%,
to {
stroke-dasharray: 0 500px;
}
}
</style>
这样就完成了 SVG 的动画啦!✌
🥳 谢谢大家!
也许你会有疑问?为什么要用 SVG 来做动画而不是 GIF ?
其实是因为 SVG 可以无损放大,方便控制大小,更加适合用来做小图标,而且嵌入到网页中,也很方便配合暗黑模式 - DarkMode。