学习 SVG 动画来丰富我的 GitHub 个人资料
一切始于 GitHub 发布了一项功能,允许在你的个人资料中添加 Readme 文件,以展示你所有已完成/正在做的精彩工作。没想到,大家竟然发现它还能用来在个人资料中添加 GIF 动图。🥳
但我当时觉得,GIF 已经过时了,SVG 才是新潮💩。只有一个问题,我对 SVG 一无所知。我是说,我的确用它做过图标和一些插图。有时我会用一些工具生成一个,然后贴到页面上。但我从未深入研究过如何从零开始创建一个 SVG 并添加动画。
无事可做,我开始谷歌搜索,惊讶地发现 MDN 上有关于 SVG 元素的详尽文档。原来,添加基本形状很简单。有像rect
、circle
、polygon
、line
和polyline
这样的标签。然后只需编写 CSS 即可实现动画效果。
太棒了!👍
所以现在我只需在屏幕上移动一个标志,就能让婴儿潮一代连续几个小时盯着它看!💪
跑题了。回到 SVG 动画。上面提到的形状或许足以让一个有创造力的人创作出一些非常酷炫的插画。但我的创造力相当有限,所以我决定做一个动态的波浪。为了弥补我的创造力不足,我学习了另一个名为 的标签path
,它能帮我创作这个波浪。🌊
想法🤓
这个想法很简单。创建多个移动的波浪,每个波浪的速度不同,并使其稍微透明一些。透明度会使波浪相交的区域变暗,从而产生多种颜色的色调。
至于横幅的尺寸,我选择了 1440 x 320,因为我喜欢这个长宽比。它不算太大,但足以添加背景信息。考虑到它在 GitHub 上显示的区域会比较小,我可以确保有足够的空间来添加其他内容。
<路径 />
所以,我开始学习如何创建路径。这很简单。路径标签有一个d
属性。获取它并不难😉。有 6 种不同类型的命令。
- 移至
- LineTo
- 三次贝塞尔曲线
- 二次贝塞尔曲线
- 椭圆弧曲线
- 关闭路径
我们只需要学习前三个。每个命令都用一个字母表示,后面跟着一些属性,这些属性是
点(xy 坐标)。
MoveToM
命令以字母或m
后跟点表示。因此,aM10,10
会将当前位置移动到点10,10
。
类似地,LineTo也包含三个命令。L
或l
会从当前位置到给定点创建一条线。例如,L10,10
会从当前位置到 创建一条线10,10
。H
或h
会创建一条到给定 x 坐标的水平线。 最后,V
或v
会创建一条到给定 y 坐标的垂直线。
三次贝塞尔曲线稍微复杂一些,用字母C
或c
表示,以 3 个点作为参数。
因此,当前位置是起点。从当前位置到点的线段x1
y1
定义了曲线在起点处的切线。从到点的线段x2
y2
定义x3
y3
了曲线在终点处的切线。x3
y3
是终点。想了解更多关于三次贝塞尔曲线的知识,请参阅这篇博文,我觉得它简短但描述性很强。你也可以参考MDN 上的 SVG 路径教程来了解更多信息。
为了巩固我们现在学到的知识,让我们解码以下 SVG。
<svg
viewbox="0 0 100 100"
width="100" height="100"
xmlns="http://www.w3.org/2000/svg">
<path
d="M10,10 V50 C10,90,90,90,90,50 V10 H10 V50"
/>
</svg>
上述代码生成的 SVG 效果如下图所示。为了清晰起见,我在图片周围添加了绿色边框。
我们的路径从 开始0,0
,第一个命令M10,10
将点移动到10,10
。然后第二个命令V50
创建一条垂直路径到10,50
。接下来,以和为参考点,C10,90,90,90,90,50
创建一条曲线,为端点。然后创建一条到 的路径。接下来,创建一条到 的路径,最后闭合路径,我们就得到了最终的图像。很简单吧?👌10,90
90,90
90,50
V10
90,10
H10
10,10
V50
实施✍️
我将图像分成四个象限,并计划在第二和第三象限添加一条曲线,如上图第一部分所示。然后,我可以稍微向内移动切线来减弱曲线。最后,我用线条闭合路径。我稍微移动了中心点,使曲线略有不同。但要确保切线与垂直轴的夹角保持不变。这确保了曲线在动画时看起来是连续的。最终,我得到了如下所示的路径。
<path d="M0,160 C320,300,420,300,740,160 C1060,20,1120,20,1440,160 V0 H0" />
如果您对上述路径理解有困难,请查看上图的最后一部分。为了更清晰,我已将路径的每个部分用颜色标记。您也可以将其与上一节进行比较,以更好地理解要点。如果您能跟上我到现在,那么我们已经顺利渡过了难关。😁
<defs /> 和 <use />
虽然,我们现在可以直接复制粘贴上面的路径,创建其他略有不同的 wave,然后就完成了。我想介绍一下defs
标签use
,这将帮助我们以更易读的方式完成所有这些操作。defs
可以用来存储图形元素,例如path
,然后稍后可以使用use
标签来使用。
我们需要做的就是给id
我们一个path
并将其放入defs
标签内,然后使用标签href
中的属性使用它use
,如下所述。
<svg
viewbox="0 0 1440 320"
width="1440" height="320"
xmlns="http://www.w3.org/2000/svg">
<defs>
<path
id='sineWave'
d="M0,160 C320,300,420,300,740,160 C1060,20,1120,20,1440,160 V0 H0"
/>
</defs>
<use href="#sineWave" />
</svg>
现在渲染的是黑色的波浪。为了解决这个问题,我们在 中使用了fill
和fill-opacity
属性path
。因此,更新后的路径如下所示。
<path
fill="#0099ff" fill-opacity="0.2"
id='sineWave'
d="M0,160 C320,300,420,300,740,160 C1060,20,1120,20,1440,160 V0 H0"
/>
动画🤤
如果你已经熟悉 CSS 动画,那么本节对你来说应该轻而易举。思路很简单。将两个波浪(我们上面创建的)水平堆叠,然后简单地将它们从 0 平移到 100%。重复以上步骤。如下所示。
这里的黑框代表用户的视口。
为了实现这一点,我们添加了另一个use
标签,但将x
属性设置为-100%
。将wave
类应用于这两个use
标签。然后创建一个动画,将 x 从 平移到0%
,100%
并将此动画应用于我们的wave
类。
<svg
viewbox="0 0 1440 320"
width="1440" height="320"
xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">
.wave {
animation: wave 8s linear infinite;
}
@keyframes wave {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(100%);
}
}
</style>
<path
fill="#0099ff" fill-opacity="0.2"
id='sineWave'
d="M0,160 C320,300,420,300,740,160 C1060,20,1120,20,1440,160 V0 H0"
/>
</defs>
<use class="wave" href="#sineWave"/>
<use class="wave" x="-100%" href="#sineWave"/>
</svg>
最后,我又添加了两个类似的波浪,唯一的区别是我使用了scaleY
transform CSS 属性来改变波浪的振幅。你可以在CodePen上查看最终的 SVG 效果。
额外提示🤗
我还在横幅上添加了一些文字。这本来很简单,因为 SVG 支持 Google 字体,但GitHub 的内容安全策略不允许从外部来源下载字体。因此,我使用这个实用程序创建了一个 SVG 路径,并将其复制到最终的 SVG 文件中。可以在我的GitHub 个人资料中查看。
结论
我对 SVG 动画的了解还只是皮毛,但已经创作出了一些我认为很酷的东西。有没有更好的方法?还有其他值得我探索的有趣内容吗?请在下方评论区留言,或在Twitter上给我留言。
更新
我的朋友向我展示了SVG Path Visualizer,我发现它对于可视化变化路径非常有用。
我们还发现网上有很多 SVG 示例,可以使用defs
和use
标签轻松调整。为了测试这一点,我修改了这个 Codepen示例,并为他创建了一个横幅,您可以在他的GitHub 个人资料中查看。