先看一个动画效果,这种小飞机沿路径飞行(路径部分线段变成绿色是录屏软件出了问题)。json
这种动画效果最多见于发送信息后,两个不一样位置之间的导航指向等等,总之使用场景仍是不少的。对于SVG动画来讲,这种效果是最最简单不过,只须要一个路径外加几个属性的简单设置就能完成,简单到不算飞机图形的话,两句代码,而整个SVG文件只有1K左右大小,咱们由浅入深,从基础开始,开启SVG路径动画之门。bash
咱们把动画元素拆解一下,由两个部分组成,一个是路径,一个是沿路径运动的图形元素。svg
关于path路径,SVG官方的定义以下:函数
各位UI设计师们,线性代数可还会?彻底不记得了?很好,由于上面这些吓唬人的知识在这个路径动画中通通用不着(你特么是在逗我?(¯﹃¯))(了解贝塞尔曲线的绘图原理多用于曲线非简单规律变化的复杂动画,不过如今有Airb
nb的Lottie神器了,用AE来作复杂的动画转成json文件是捷径,数学大神们除外。)
咱们说过了,AI里面的路径在导出SVG时一样会生成对应的<path>
标签。若是你是第一次看个人关于SVG动画的文章也没有关系,咱们一步步分解。
第一步:AI绘制一条由起点A到终点B的曲线,随便描个边。工具
<path>
标签部分。个人以下:
<path fill="none" stroke="#78EADF" stroke-width="30" stroke-linecap="round" stroke-miterlimit="10" d="M66.9,517 c0,0-37.8-194,125.1-161.9S427.6,371.5,350,205.7S439.3,23.4,544,62.2"/>复制代码
关于路径描边的各个属性值再也不赘述,注意标签中d=""部分,后面咱们的路径动画时要调用的就是这个路径。动画
path路径的参数由AI导出的SVG路径中的d生成。ui
<animateMotion>
关于路径动画最基础的语法简单到以下:url
<animateMotion path="" dur=""/>
<!--dur定义动画时间-->复制代码
其中path即为咱们在AI中绘制路径自动生成的d="" 所包含的定义路径曲线的部分。
如今,若是我定义一个最简单的圆形circle,加上路径动画属性,已经能够实现动画效果了,代码以下:spa
<circle fill="#F8B62D" r="20">
<animateMotion path="M66.9,517 c0,0-37.8-194,125.1-161.9S427.6,371.5,350,205.7S439.3,23.4,544,62.2" dur="3s"/>
</circle>复制代码
动画效果以下:设计
这里还有一个方法,就是咱们给蓝色路径定义一个id,而后路径动画来引用这个id,代码以下:
<!--road为咱们定义的路径id-->
<path id="road" fill="none" stroke="#78EADF" stroke-width="30" stroke-linecap="round" stroke-miterlimit="10" d="M66.9,517 c0,0-37.8-194,125.1-161.9S427.6,371.5,350,205.7S439.3,23.4,544,62.2"/>
<circle fill="#F8B62D" r="20">
<animateMotion dur="3s">
<mpath xlink:href="#road"/> <!--经过路径连接属性调用定义的路径-->
</animateMotion>
</circle>复制代码
这两种方法都可,重点是第二种方法,后面将要揭秘。
看了上面的是否是感受so easy,但这确定不是咱们的需求,开始抛砖引玉,好比,我准备作一个沿路径奋力爬行的小瓢虫的动画。先准备素材,在AI中绘制一只小瓢虫,好比图层我命名beatles
而后获得一堆<g id="beatles">……</g>
的SVG代码。
接下来就很简单了,用甲虫的图形来替换上面动画中的圆形,其余不变。获得代码以下:
<g id="beatles">
……<!--此处省略绘制甲虫的代码若干-->
<animateMotion path="M66.9,517 c0,0-37.8-194,125.1-161.9S427.6,371.5,350,205.7S439.3,23.4,544,62.2" dur="3s"/>
</g>复制代码
期待已久的时刻来了,正常思路,咱们的小瓢虫能够沿着路径爬行了。各位看官先不要激动,此时,你看到的动画应该是这个样子的(为了方便观察,我把画布调整了大小,留出足够的空间)。
先来看一句话: 定义了路径动画的图形会把路径的起点做为原点。读起来拗口且难懂,炒个栗子吧。我绘制的路径起点坐标为X=66.9,Y=517,对于了解SVG路径的小伙伴们都知道,其实就是path的起点M值。那对于甲虫来讲,(66.9,517)才是它坐标系的原点,而不是(0,0)。以下图所示,整个坐标系向右偏移了66.9px,向下偏移了517px。
既然知道偏移的值,再把它放回去,放回去的话就很简单了,咱们只要把甲虫移动到画布的左上角原点的位置(即x=0,y=0)
这个方法至关于方法1的扩展,你可使用defs来定义图形,use标签来调用,一样须要图形位于画布原点,代码以下:
<defs>
<g id="beatles">
……<!--此处为绘制瓢虫的代码-->
</g>
</defs>
<use xlink:href="#beatles" x="0" y="0">
<animateMotion dur="3s">
<mpath xlink:href="#road"/> <!--方法2和方法1因为路径是同一条,因此都适合用调用路径的方法-->
</animateMotion>
</use>复制代码
用defs来定义图形的好处是,你可使用use标签在不一样位置重复调用这个图形,好比我下面说明运动速率时摆放的5只小甲虫。
由方法1和方法2咱们得出一个结论,图形绘制的时候无所谓位置,只要最后在画布的左上角原点就能够了。
上面的那个方法虽然能够实现正常路径运动,但实际中存在一个问题(个人动画播放时使用了无限循环,因此看不出)。当动画设置了延迟开始(eg. begin="2s")时,甲虫在动画开始前并非乖乖的待在起点A,而是移动后的位置,画布左上角,2s后动画开始播放,甲虫才回到A点。来看下面这种解决方案,从新定义图形的移动路径。
跟着我左右右手一个慢动做,右手左手慢动做重播……咱们用相同的方法来移动,不过,此次咱们移动的是路径,记得选择“复制”,或者干脆点,直接把起点拖到画布的原点。
<animateMotion path="M0,0 c0,0-37.8-194,125.1-161.9s235.7,16.5,158.1-149.3s89.2-182.3,194-143.5" dur="3s"/>复制代码
如今,全部都恢复正常,咱们的小甲虫又能够乖乖的从A爬到B了,并且不管什么时候,起点和终点都是咱们预期值。(但这个方法有个很大的bug,后面再说)
做为有追求的设计师,这个动画效果是否是感受low到爆?首先,瓢虫移动速度不符合物理规律,匀速运动,其次,身体没有相应的转动,生硬不生动。好了,来,加上这几个属性,改善一下。
先给animateMotion加上下面的代码:
calcMode="spline" keySplines="" keyTimes="0;1"复制代码
calcMode属性定义动画的类型,一共四个属性值,其余不说了,"spline"要搭配后面的keySplines和keyTimes属性一块儿使用,以上代码的意思是宣告“我要来为所欲为的控制运动速率了!”
keySplines值的设定与CSS的贝塞尔曲线相同。
关于运动速率的贝塞尔曲线(说好了不提它,又来!)有个在线工具能够借助:cubic-bezier.com/
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值就用最基础的就好。
这个简单,只有一句代码:rotate="auto",此时的路径动画已经实现的有模有样了。
好了,开始放能够复用的代码并注释,一切不能复用的SVG动画代码都是耍流氓!
<svg width="" height="">
<path id="road" fill="none" d=""/><!--路径所有由AI直接生成-->
<g>
……
<!--此处为若干图形代码-->
<animateMotion dur="" repeatCount="" rotate="auto" calcMode="spline" keyTimes="0;1" keySplines="" ><mpath xlink:href="#road"/></animateMotion>
</g>
</svg>复制代码
嗯,over,就是介么简单。剩下的只是填空。
好比dur定义所有动画须要的时间,keySplines定义运动速率类型,repeatCount定义播放次数,上面都有一一解释。
那么利用路径动画,都能实现什么效果呢,来继续看:
如今我要实现一个小甲虫渐行渐远的效果,为了让效果看起来更逼真,我把底图描边路径从新作了一下,而后把keySplines="0,0,.58,1"即运动速率为ease-out慢结束,以下:
这个效果实现也不过再加一句缩放动画代码
<animateTransform dur="" attributeName="transform" fill="freeze" type="scale" from="1 1" to="0.5 0.5" />复制代码
时间与路径动画保持一致,type="scale" from="1 1" to="0.5 0.5"表示宽高缩小到原来1/2。
你能够搞得很复杂,好比伴随甲虫腿的摆动,但涉及到复合动画,好麻烦,这也是我为何没有用一只带腿的甲虫的缘由,哈哈。
结合描边动画和蒙版,咱们能够实现下面这种效果:
<svg width="600" height="600" >
<style>
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
#helix{
stroke-dasharray:2006; /*2006为螺旋线的长度*/
stroke-dashoffset:2006;
animation: dash 4s linear forwards; /*蒙版动画的速率和时间与飞机路径动画保持一致*/
animation-delay:0.2s; /*为了让飞机稍微领先,设置了蒙版动画0.2秒的延迟*/
}
</style>
<mask id="helix">
<!--蒙版调用定义的描边动画helix,d=""包含部分为螺旋线的路径-->
<path fill="none" stroke="#fff" stroke-width="16" stroke-linecap="round" d=""/>
</mask>
<path mask="url(#helix)" id="road" fill="none" stroke="#78EADF" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="0,30" d=""/>
<g id="plane">
…<!--此处飞机代码若干-->
<animateMotion fill="freeze" dur="4s" rotate="auto" calcMode="spline" keyTimes="0;1" keySplines="0,0,1,1" ><!--keySplines值的设定要与描边动画保持一致,若是上面animation定义了ease,则这里也要对应改为".25,.1,.25,1"-->
<mpath xlink:href="#road"/>
</animateMotion>
</g>
</svg>复制代码
知识点总结:
①动画的路径直接经过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仅用来提供基础图形。由于不记得都在哪些文章中提到过路径动画了,因此无法一一更正,这是初始篇,因此但愿全部的阅读这篇文章的人都能看到,不要被我带坑里哦。