如何用CSS制作SVG动画
说到SVG动画,你一般会想到的方式是利用JavaScript库控制SVG动画。然而,这不是唯一的方式,CSS也可以控制SVG中的部分路径,以创造动画效果。了解CSS对SVG的控制,意味着你可以用简单的CSS创造平滑的、动态的图标效果,使得作品更加出彩。

学会和CSS结合的SVG,你就能够将页面上的更多元素替换为SVG,这样你就可以在实现类似动画的同时将页面进行进一步优化。而如果你充分应用SVG动画,等待你的是无限的可能性。
01 创建保存基础图形
首先,你要先制作以一个SVG用来操作。在这篇教程里,我们用Illustrator创建一个简单的SVG图形作为范例。在Illustrator中,创建好图形后,点击“另存为”然后在下拉菜单中选择SVG即可。在保存确认界面,你可以不进行保存,而是点击“SVG代码”按钮,在浏览器里查看SVG的组成代码。
02 优化SVG为网络所用

删去不必要的SVG标签可以让SVG图形更小也更容易处理。本质上,你应该直接用文本编辑器打开,然后移除SVG代码内的空标签和Meta数据。但我们有工具可以帮我们做这件事:
这是一个开源工具,可以在线使用。你只需要将原SVG代码黏贴在“Paste markup”的区域,然后点击右侧的按钮即可将优化过的代码复制出来。
03 创建HTML文档
接下来,打开你的代码编辑器并创建一个空的HTML文档。在这篇教程中,我们将CSS代码写在main.css中,因此请把这个文件也准备好。另外,因为这个教程是专门用来制作动画的,因此我们引用Bootstrap 4.1.3的仅有CSS的版本。
04 创建版面
接下来,我们创建一个基础排版,以给SVG安排一个位置。我们写好文件头和两列布局,左侧放置文字,而右侧放置我们要制作动画的SVG。在教程的示例里,我们在body标签中加入了一个静态SVG作为背景,仅仅是为了美观。
如果这一步你不知道怎么做,请先学习HTML基础。
05 放置SVG
接下来我们要放置刚才绘制的SVG图形了。将优化过的SVG代码黏贴在右侧的一列里,如果你引用了bootstrap,请给SVG加上img-fluid类以确保它在移动端的缩放效果。
06 给SVG增加各种类
既然我们要用CSS控制,就必须给SVG中的特定部分增加类,这样CSS才能知道应该控制哪个部分。增加多少类看你的需求,这是没有上限的,也就意味着创建复杂的SVG动画是有可能的。
下面的示例代码,是我们在教程里使用的SVG部分的代码,你可以看到我们已经增加了两个类rectBackground和rectText上去。
<svg>
<g>
<rect class="rectBackground" width="147.4107"
height="68.7917" x="31.2946" y="114.1042"
rx="4.5882" ry="3.9565" fill="#2a7fff"/>
<path class="rectText" d="..." vector-effect="non-scaling-stroke" stroke-width=".470476156" font-size="12" fill="#fff"
fill-rule="evenodd" stroke="#fff" stroke-linecap="round"/>
</g>
</svg>
07 设置初始状态
即便类在SVG里,CSS的选择器工作原理也是一样的。当我们设置好了类,就可以使用SVG子标签和设置的类名称进行选择。我们预设在初始状态,SVG的两个部分(文字和背景)都是隐藏的,因此透明度opacity的预设值要为0。
path.rectText {
opacity:0;
}
rect.rectBackground{
opacity: 0;
}
08 声明动画
接下来,我们需要声明动画的名称和关键帧,这样CSS才知道让我们要求执行动画的时候具体该做什么。我们要绘制两个动画,命名为textDraw和rectFade。然后,在每个命名下,我们要附加几个名称。在textDraw动画下,我们增加了3个名称,意味着这是一个三步骤动画。
@keyframes textDraw {
0%{}
50%{}
100%{}
}
@keyframes rectFade{
from{}
to{}
}
09 关联动画和属性

接下来,我们将rectFade效果附加到rectBackground元素上,时间设置为1秒,效果选择easeOut(擦除)并设置动画曲线以让动画更加平滑。然后,我们给动画添加forwards属性,这样动画就可以在播放结束后保持在最后一个关键帧的状态。
rect.rectBackground{
opacity: 0;
animation: rectFade 1s cubic-bezier(0.645,
0.045, 0.355, 1) forwards;
}
10 背景正方形动画

正方形只有2个关键帧,所以我们只需要设置好初始状态和结束状态的属性即可。在初始阶段的from帧,我们将宽度width设置为1%,在结束的to帧,我们设置宽度width为100%并设置透明度opacity为1(因为它会继承父对象的初始状态opacity 0)。
@keyframes rectFade{
from {
width: 1%;
}
to {
width:100%;
opacity: 1;
}
}
11 文字动画
接下来,我们给文字加上一个书写出现的效果。我们首先给textDraw动画4秒钟的动画时长,然后使用不同的渐变曲线,让它的动画播放速度随时间产生变化,不至于过分生硬。
path.rectText {
opacity:0;
animation: textDraw 4s
cubic-bezier(.56,-0.04,.32,.7) forwards;
}
12 推迟动画
我们希望文字动画在背景的长方形出现完成后再开始进行,所以需要推迟它。而由于长方形的动画持续1秒,因此我们要推迟相应的(或更多的)时间。
path.rectText {
opacity:0;
animation: textDraw 4s
cubic-bezier(.56,-0.04,.32,.7) forwards;
animation-delay: 1s;
}
13 模拟线条绘制

为了得到线条绘制效果,我们需要使用stroke-dasharray和stroke-dashoffset两个参数。注意,你使用的SVG将决定参数的属性值,你可以用开发者工具,将stroke-dasharray从0一直往上增加,直到图形轮廓完全被显示完成的那个点,此时的数值就是你用于替换下方735的属性。
path.rectText {
opacity:0;
stroke-dasharray: 735;
animation: textDraw 4s
cubic-bezier(.56,-0.04,.32,.7) forwards;
animation-delay: 1s;
}
14 设置画线的初始关键帧内容
现在我们有了外轮廓,然后我们来编辑它的长度。我们要的效果是,在轮廓绘制完成后填充色出现。因此,我们先把stroke-dashoffset设置为dasharray的收尾值(或更大),并且设置透明度和填充、描边的颜色(如果父对象没有这方面的设置的话)。
0%{
fill:rgb(255, 255, 255, 0);
stroke:#fff;
stroke-dashoffset: 800;
opacity: 1;
}
15绘制完成线条
下面我们来到第二个关键帧40%的位置,首先把stroke-dashoffset设置为0,让线条覆盖路径。然后我们再次设置填充的透明度,以免它在这一步显示出来。
40%{
stroke-dashoffset: 0;
fill:rgb(255, 255, 255, 0.0);
}
16 填充颜色
在最后的关键帧,我们给整个图形填充白色就可以了。这里我们主要调节的是填充里的alpha值(即rgb的第四个值,透明度),这样就可以在两个关键帧之间实现渐变出现的效果。
100%{
fill:rgb(255, 255, 255, 1);
stroke-dashoffset: 0;
opacity: 1;
}