先看一个动画效果,这种小飞机沿路径飞行(路径部分线段变成绿色是录屏软件出了问题)。
这种动画效果最常见于发送信息后,两个不同位置之间的导航指向等等,总之使用场景还是很多的。对于SVG动画来说,这种效果是最最简单不过,只需要一个路径外加几个属性的简单设置就能完成,简单到不算飞机图形的话,两句代码,而整个SVG文件只有1K左右大小,我们由浅入深,从基础开始,开启SVG路径动画之门。
我们把动画元素拆解一下,由两个部分组成,一个是路径,一个是沿路径运动的图形元素。
1.path路径获得
关于path路径,SVG官方的定义如下:
- M = moveto
- L = lineto
- H = horizontal lineto
- V = vertical lineto
- C = curveto
- S = smooth curveto
- Q = quadratic Bézier curve
- T = smooth quadratic Bézier curveto
- A = elliptical Arc
- Z = closepath这些还不是最恐怖的,最恐怖的莫过于下面的三次贝塞尔曲线和二次贝塞尔曲线Q。
各位UI设计师们,线性代数可还会?完全不记得了?很好,因为上面这些吓唬人的知识在这个路径动画中统统用不着(你特么是在逗我?(¯﹃¯))(了解贝塞尔曲线的绘图原理多用于曲线非简单规律变化的复杂动画,不过现在有Airb
nb的Lottie神器了,用AE来做复杂的动画转成json文件是捷径,数学大神们除外。)我们说过了,AI里面的路径在导出SVG时同样会生成对应的<path>
标签。如果你是第一次看我的关于SVG动画的文章也没有关系,我们一步步分解。 第一步:AI绘制一条由起点A到终点B的曲线,随便描个边。 <path>
标签部分。我的如下: 复制代码
关于路径描边的各个属性值不再赘述,注意标签中d=""部分,后面我们的路径动画时要调用的就是这个路径。
path路径的参数由AI导出的SVG路径中的d生成。
2.路径动画<animateMotion>
关于路径动画最基础的语法简单到如下:
复制代码
其中path即为我们在AI中绘制路径自动生成的d="" 所包含的定义路径曲线的部分。
现在,如果我定义一个最简单的圆形circle,加上路径动画属性,已经可以实现动画效果了,代码如下:复制代码
动画效果如下:
这里还有一个方法,就是我们给蓝色路径定义一个id,然后路径动画来引用这个id,代码如下:
复制代码
这两种方法均可,重点是第二种方法,后面将要揭秘。
3.任意图形的路径动画
看了上面的是不是感觉so easy,但这肯定不是我们的需求,开始抛砖引玉,比如,我准备做一个沿路径奋力爬行的小瓢虫的动画。先准备素材,在AI中绘制一只小瓢虫,比如图层我命名beatles
然后得到一堆<g id="beatles">……</g>
的SVG代码。
…… 复制代码
期待已久的时刻来了,正常思路,我们的小瓢虫可以沿着路径爬行了。各位看官先不要激动,此时,你看到的动画应该是这个样子的(为了方便观察,我把画布调整了大小,留出足够的空间)。
4.任意图形的位置校正
先来看一句话: 定义了路径动画的图形会把路径的起点作为原点。读起来拗口且难懂,炒个栗子吧。我绘制的路径起点坐标为X=66.9,Y=517,对于了解SVG路径的小伙伴们都知道,其实就是path的起点M值。那对于甲虫来说,(66.9,517)才是它坐标系的原点,而不是(0,0)。如下图所示,整个坐标系向右偏移了66.9px,向下偏移了517px。
4.1 方法1——把甲虫拉回它应该在的位置
既然知道偏移的值,再把它放回去,放回去的话就很简单了,我们只要把甲虫移动到画布的左上角原点的位置(即x=0,y=0)
4.2 方法2——使用SVG的defs元素
这个方法相当于方法1的扩展,你可以使用defs来定义图形,use标签来调用,同样需要图形位于画布原点,代码如下:
复制代码 ……
用defs来定义图形的好处是,你可以使用use标签在不同位置重复调用这个图形,比如我下面说明运动速率时摆放的5只小甲虫。
由方法1和方法2我们得出一个结论,图形绘制的时候无所谓位置,只要最后在画布的左上角原点就可以了。4.3 方法3——重新定义移动路径
上面的那个方法虽然可以实现正常路径运动,但实际中存在一个问题(我的动画播放时使用了无限循环,所以看不出)。当动画设置了延迟开始(eg. begin="2s")时,甲虫在动画开始前并不是乖乖的待在起点A,而是移动后的位置,画布左上角,2s后动画开始播放,甲虫才回到A点。来看下面这种解决方案,重新定义图形的移动路径。
跟着我左右右手一个慢动作,右手左手慢动作重播……我们用相同的方法来移动,不过,这次我们移动的是路径,记得选择“复制”,或者干脆点,直接把起点拖到画布的原点。复制代码
现在,所有都恢复正常,我们的小甲虫又可以乖乖的从A爬到B了,而且无论何时,起点和终点都是我们预期值。(但这个方法有个很大的bug,后面再说)
作为有追求的设计师,这个动画效果是不是感觉low到爆?首先,瓢虫移动速度不符合物理规律,匀速运动,其次,身体没有相应的转动,生硬不生动。好了,来,加上这几个属性,改善一下。
5. 运动速率的设定
先给animateMotion加上下面的代码:
calcMode="spline" keySplines="" keyTimes="0;1"复制代码
calcMode属性定义动画的类型,一共四个属性值,其他不说了,"spline"要搭配后面的keySplines和keyTimes属性一起使用,以上代码的意思是宣告“我要来随心所欲的控制运动速率了!”
keySplines值的设定与CSS的贝塞尔曲线相同。关于运动速率的贝塞尔曲线(说好了不提它,又来!)有个在线工具可以借助:keyTimes值(0;1)是最简单的一种,没有对运动过程进行分割,如果你想玩出更深的套路,可以把路径截成好几段,然后定义不同的keySplines值。再炒个栗子。
keyTimes="0;0.66;1" keySplines=".42,0,1,1;0,0,1,1;" 就是路径的前2/3,我希望用ease-in函数定义速度,路径的后1/3线性速度,但在衔接处会抖一下,因为实在使用场景很少,所以keyTimes值就用最基础的就好。6. 跟随路径曲度的旋转方向
这个简单,只有一句代码:rotate="auto",此时的路径动画已经实现的有模有样了。
好了,开始放可以复用的代码并注释,一切不能复用的SVG动画代码都是耍流氓!
复制代码
嗯,over,就是介么简单。剩下的只是填空。
比如dur定义全部动画需要的时间,keySplines定义运动速率类型,repeatCount定义播放次数,上面都有一一解释。那么利用路径动画,都能实现什么效果呢,来继续看:
7.1 路径动画功能扩展——伴随图形变化
现在我要实现一个小甲虫渐行渐远的效果,为了让效果看起来更逼真,我把底图描边路径重新做了一下,然后把keySplines="0,0,.58,1"即运动速率为ease-out慢结束,如下:
这个效果实现也不过再加一句缩放动画代码
复制代码
时间与路径动画保持一致,type="scale" from="1 1" to="0.5 0.5"表示宽高缩小到原来1/2。
你可以搞得很复杂,比如伴随甲虫腿的摆动,但涉及到复合动画,好麻烦,这也是我为什么没有用一只带腿的甲虫的原因,哈哈。7.2 路径动画功能扩展——搭配描边动画+蒙版
结合描边动画和蒙版,我们可以实现下面这种效果:
复制代码
知识点总结:
①动画的路径直接通过AI绘制后导出的SVG的d值获得。②图形元素移动到画布原点后再生成对应的SVG代码。③通过定义calcMode、keyTimes以及 keySplines来修改运动速度。④定义rotate属性来实现跟随路径曲率的旋转效果。⑤与其他动画的组合,需要多多的创意。
补充部分(更正):
CSS3有路径动画属性!有路径动画属性!有路径动画属性!在写这篇文章时,一直以为路径动画是CSS3唯一不可取代SIML实现的动画,直到今天,我看到了这个,抑制不住的激动٩(๑>◡<๑)۶,我CSS3终于动画部分大统一了。
@keyframes move{ 0%{offset-distance:0%; }100%{offset-distance:100%; } }#move{ offset-path:path('');animation:move 1s ease ;}复制代码
是的,你没有看错,就是offset-path
和offset-distance
两个属性。offset-path
用于定义路径部分,offset-distance
控制元素在路径上的运动距离。
至此,SVG+CSS3动画终于得以完美,所有动画部分均由CSS3来控制,SVG仅用来提供基础图形。因为不记得都在哪些文章中提到过路径动画了,所以没法一一更正,这是初始篇,所以希望所有的阅读这篇文章的人都能看到,不要被我带坑里哦。