阅读 3117

UI设计师福利之手把手打造SVG动画应用的微场景

SVG动画即使可以做的炫酷爆炸,但与AE不同,它不能导成视频,不能导成GIF,而且考虑到AI与SVG的互通性,SVG动画合适用来做矢量卡通风格,放到实际应用中,不太建议利用SVG动画做太复杂的效果,毕竟UI设计师不是动效设计师,且动画做起来确实复杂的多。但虽然不适合大舞台,我们却可以用SVG动画来打造一些微场景的应用,首先,动画属性的设置极其简单,其次,效果却比较出彩,下面来看几个应用。

1.利用轨迹动画的表情

先看效果

表情
表情

除了会动的眼睛之外,其他对于UI设计师来说,实在是太简单了,而左顾右盼的眼睛,只用了最最基础的轨迹动画。看过我之前的其他几篇文章的小伙伴应该很轻松的能做出来这种效果吧。
说一下实现的方法。
第一步,把动静元素分开。
所有的SVG动效,都要把动静元素分开,这是非常关键的一部,静态元素直接导出,动态元素单独赋予动画属性。

为了不让自己迷糊,在AI里面绘制图形的时候,一定建好图层,重要的问题说三遍,图层!图层!图层!我知道,除非绘制非常复杂的图形,UI设计师在使用AI时是不太愿意使用图层的,毕竟一个快捷键ctrl+2就能锁定,还有隔离选中路径,外加编组,一个图层里来来回回的操作更加快捷。但从现在开始,如果需要做SVG动画,一定要养成这种分图层的好习惯,否则AI导出的SVG将乱到崩溃。

绘制底图
绘制底图

比如这个案例里,我建了三个图层,分别命名为base,eye,path,依次承载底图,运动的眼睛,运动的路径。底图里扔进去背景、手机、一只mbe风格的蛋。
继续

眼睛和路径
眼睛和路径

命名eye的图层里自然是放眼睛了,然后path上绘制路径。红色虽然比较刺眼,但是在SVG中我能一眼看出嘛,而且绘制运动路径只是为了提供一个路径值,实际又不显示的嘛。
静的元素有了,动的元素有了,动的路径有了,好了,开始搞一搞代码。

<svg>
<g id="base"><!--以下为AI导出的组成底图的代码-->
……
</g>
<g id="eye">
<circle cx="0" cy="0" r="">
<animateMotion path="" dur="1.5s" repeatCount="indefinite" calcMode="spline"  keySplines=".42, 0, .58, 1" keyTimes="0;1" /><!--path对应左眼的运动路径-->
</circle>
<circle cx="0" cy="0" r="">
<animateMotion path="" dur="1.5s" repeatCount="indefinite" calcMode="spline"  keySplines=".42, 0, .58, 1" keyTimes="0;1" /><!--path对应右眼的运动路径-->
</circle>
</g>
</svg>复制代码

代码部分就是介么简单。另外关于眼睛对应的<circle>标签,AI导出的cx和cy值肯定不是零,那为什么要修改,请移步路径动画的文章,里面有详解,包括各个动画属性值对动效的影响。对于这个动画效果而言,唯一需要注意的是SVG动画属性并不像CSS3的animation-direction:alternate这种属性支持逆向播放,也就是说如果眼睛的效果想做成“左右对称震荡”的类型,有两个解决方法,一个是绘制成下面这种路径后手动修改path值补充一个反向路径,这需要了解贝塞尔曲线,略有难度。

还有一个方法UI设计师会更喜欢,就是再原路径基础上再绘制一段路径,终点就是原路径的起点,路径差不多重合就可以了,不用那么严格。

补充反向路径
补充反向路径

然后把导出的path值进行替换,就能得到下面这种效果(重点看眼睛~)

改变眼睛运动路径后的动效
改变眼睛运动路径后的动效

嗯,so easy。

2.利用旋转动画实现的运动车轮效果

这个动效也是特别的简单,只用到transform:rotate旋转动画属性,但用对地方的话,效果还蛮好,所以特意拿出来说一下。
先来个场景设定


最终的动画是我想要实现蓝天白云背景下,一辆自行车行驶的情景。先来动静拆分,背景和自行车架是静态的,车轮是动态的,然后再AI里面,搞清楚图层关系就OK了,我的由下到上的顺序为 背景stage——后车轮back——前车轮head——自行车架body ,然后,AI,直接导出SVG。
这里有一个重要工作,就是关于前后车轮圆形的中心点,这是我们旋转动画的原点。为了不去代码里扒拉出来,可以手动记录下来。

只要加上下面的CSS样式,车轮就可以动起来了。

<style>
@keyframes bicycle{
0%{transform:rotate(0)}
100%{transform:rotate(360deg)}/*定义旋转动画*/
}
#head{animation:bicycle 0.5s  linear infinite ; transform-origin:165px 440px}/*transform-origin根据自己的车轮的圆心定义*/
#back{animation:bicycle 0.5s  linear infinite; transform-origin:450px 440px}
</style>复制代码

非常简单的定义,需要注意的地方一个是圆心对应的旋转的中心点,另外关于运动速率,定义为线性linear。
好嘞,转起来嘞。

旋转的车轮
旋转的车轮

有没有看出哪里不对?
再提示一下,车轮旋转的方向
顺时针!然后想象一下我们生活中,车把在左侧时,车轮要逆时针旋转才是前进,这是一辆没有追求的不停后退的自行车啊。
修改方法自然很简单,transform:rotate(-360deg)就好了。
先不着急放改之后的效果图,继续深入想一下。自行车车轮倒是转起来了,但是运动过程缺乏真实感。问题出在哪里?
答案:背景的白云。
当运动的物体没有参照物还好,一旦有了参照物,前进的物体对应参照物要后退。所以这里,我不小心给自己挖了个坑(早知如此何必当初画蛇添足/(ㄒoㄒ)/~~)
让白云后退意味着白云由静态元素变成了动态元素,根据我们的“动静分离法则”,我需要把白云元素从背景层里分离出来,单独放到一个命名为cloud的图层中。
白云的无限循环的运动我准备用下面的方法实现,建一个宽度是背景2倍的元素,执行位移动画,直到B完全进入背景图层中,循环这一过程。

运动示意图
运动示意图

现在最大的问题就是要解决无限循环的运动周期无缝对接的问题,换句话说,当B完全进入背景图层后,下一个循环从头开始,此时A位于背景图层,那瞬间转换的时候怎么才能没有跳跃感?很简单,让B与A完全重合。
在AI里面实现更简单了,只要把原来的白云元素移动复制,左移距离等同于背景宽度。
给白云元素增加一个位移动画

@keyframes move{
0%{transform:translateX(0)}
100%{transform:translateX(600px)} /*600为背景的宽度*/
}
#cloud{animation:move 2s linear infinite;}复制代码

为了测试是不是达到了无缝拼接的效果,我暂时把白云运动的速度加快了(一个位移周期2s),看一下白云的运动。

无缝拼接的运动的白云
无缝拼接的运动的白云

当然,和自行车组合的时候白云速度要很慢,毕竟自行车达不到风驰电掣的速度。
考虑到有天空了,索性把大地也填上,同样的方法,给自行车增加一道地平线,图层命名为earth。此处又有坑,白云也就罢了,速度慢点就行,具体多慢随心情。地平线后退的速度就不能这么随心所欲了,因为它们之间存在下面这种关系。
车轮旋转一圈距离=地平线后退距离
在我们位移动画中,位移距离是固定的,速度由一个动画周期需要的时间决定,换算到具体时间怎么办?
我们假设地平线后退600px(场景宽度)需要的时间为T1,速度C=600px/T1,车轮旋转一圈需要的时间为T2,同时C*T2=车轮周长(2πR),得到T1=(600px*T2)/2πR。
在我们这个案例里,T2定义为0.5s,车轮半径R为75,算出来T1≈0.64,所以对应地平线动画设置如下

#earth{animation:move 0.64s linear infinite;}复制代码

现在看一下最终的效果

正向车轮
正向车轮

然后比较一下最开始悬空的只有车轮转动的效果,感觉真实了好多。
当然了,如果你有更多的时间和精力,甚至可以不把白云作为一个整体移动,而是每一朵单独拆分出来,设置不同的透明度和速度,异步播放,效果更好。还有其他元素可以自己随意添加。

3.利用变形动画实现的风吹动头发的效果

前面写过的SVG变形动画真的很!复!杂!我自己偶尔练手的时候都会感觉繁琐,繁琐,但实际应用时,真的不需要太复杂的图形变化,来看下面这个案例。
这是我的底图

底图
底图

效果来个简单的,微风轻拂秀发吧。依据“动静分离大法”,我的AI中的图层拆分成这三个部分。
由下到上的顺序如下图所示

动静元素拆解
动静元素拆解

请忽略那个诡异的刘海,没有办法……
对应的SVG文件应该是下面这种

<SVG>
<g id="base">
…底图代码…
</g>
<g id="hair">
<path d=""><!--头发-->
</g>
<g id="face">
…面部其他元素代码…
</g>复制代码

头发随风飘摇那是必须要用变形动画,而且是最最简单的那种,修改几个锚点的位置,调整一下形状就可以了。不会的移步SVG变形动画文章里,有详解。
为了方便调整,可以像我这样另存到一个新的AI文件里面删除其他元素进行修改

修改头发
修改头发

我们通过修改能得到两个d值,一个是飘到左边的一个是飘到右边的。然后给原SVG增加样式文件

<style>
@keyframes blow{
0% {d:path('')} /*对应头发飘到左边的d值*/
100%{d:path('')}/*对应头发飘到右边的d值*/
}
#hair {animation: blow 2s ease-in-out infinite alternate;}
</style>复制代码

再做一个小修改,把

<g id="hair">
<path d="">
</g>复制代码

改成

<path id="hair" />复制代码

放效果

微风轻拂
微风轻拂

因为我设置的一个周期的时间比较长,所以是这种缓动效果。
所以即使SVG变形动画应用,也尽量只用在整个图形的局部元素上,画龙点睛就好啦。