先放上效果图,再说实现方法。
bash
不管何种形式的SVG动图,第一步天然离不开咱们的“动静分离大法”。静态图分离出来以下:函数
<g id="base">
…对应静态底图的代码…
</g>
<g class="emotion">
<path id="left"/>
<path id="right"/>
<path id="mouse"/>
</g>复制代码
"left"为左眼路径(因为悲伤sad的左右眼是对称关系,因此没有定义一组动画屡次引用);"right"为右眼路径;"mouse"为嘴巴路径。为了方便定义描边属性,我把全部的表情元素放到了一个组里。这样我就能够经过定义CSS属性post
.emotion path{fill:none;stroke:#615658;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}复制代码
来赋给全部的表情元素相同的描边效果了。动画
先说眼睛从圆形变成弯弯曲线的过程。首先肯定的是,确定是用了变形动画。弯弯曲线只须要一段路径就能够实现,而圆形的组成路径有四段路径,所以咱们须要改造的就是路径少的曲线,方法也很简单,只须要给其增长三个锚点,使其变成四段路径就能够了。另外圆形路径也要用剪刀剪成开放路径。其余要注意的细节调整方法再也不详细说了,变形动画的三篇文章里有详细介绍。spa
@keyframes deformLeft1{
0% {d:path('')} /*圆形路径*/
100%{d:path('')} /*笑时的弯弯路径*/
}
#left{animation:deformLeft1 1s ease}复制代码
这样就实现了左眼的变形动画。
这个动画过程没有给路径少的曲线直接增长虚拟曲线是由于试过以后效果很差。
嘴巴实现的过程是直线变曲线的过程,AI直接导出的直线必定是下面这样的3d
<line x1="" y1="" x2="" y2=""/>复制代码
而微微上翘的嘴巴是对应路径标签<path>
。咱们要作的,就是根据直线起点(x1,y1)终点(x2,y2),(水平直线的纵坐标y1与y2是等值的)将其转化成路径标签,方法也很简单,对应d值Mx1,y1c0,0,0,0,(x2-x1),0。code
@keyframes deformMouse1{
0% {d:path('')} /*直线转化后的路径*/
100%{d:path('')} /*微微上翘的嘴巴的路径*/
}
#mouse{animation:deformMouse1 1s ease}复制代码
至此,完成了第一个动画过程。
在路径的改造过程当中,请用任意一个方法保留未修改的路径,后面揭晓缘由。orm
在由微笑变伤心的过程当中,由于表示伤心的眼睛是两条直线折线绘制的,这时导出的标签是<polyline points=""/>
,固然了,若是你对贝塞尔曲线比较熟悉的话,彻底能够根据坐标值直接来转化成小c开头的路径绘制方法,不熟悉的话就把直线改为带不多不多不多一点点手柄的曲线吧。
咱们在上一个动画完成时,为了配合圆形,把眼睛弯弯的一条路径改为了四条,那么到了这里怎么办?难道再把伤心的眼睛也切成四份,好吧,即便这里能够这么操做,那最后晕晕眼睛的螺旋线?那但是N条路径组成的,难道都要以最终数量最多的路径为准,加锚点加到手软抽筋?!
因此说才要保留一份未修改的路径嘛。咱们直接用原始的路径来进行改造,由于伤心的眼睛是两条路径,因此给原始路径增长一个锚点,使路径由一条变成两条就能够啦。不管是路径上添加了几个锚点,视觉上无差,因此动画才能实现无缝拼接。cdn
@keyframes deformLeft2{
0% {d:path('')} /*变身两条路径的弯弯的眼睛*/
100%{d:path('')}/*悲伤的眼睛*/
}复制代码
咱们是给一个元素附加多个动画,语法以下:blog
#left{animation:deformLeft1 1s ease,deformLeft2 1s ease 1s}复制代码
后面依次累加,用逗号,隔开就能够了,由于第一个动画我设置了1s的完成周期,因此第二段动画deformLeft2最后的1s表示延迟1s后执行。
之因此没有采用定义多个关键帧的方式来实现多个变形动画,一个是考虑到最后的螺旋线路径数量太多,固然,最重要的是每个变形动画完成我都采用了ease函数,使每段动画增长一点停顿感。
对于第二个动画而言,嘴巴的变形很简单,就再也不赘述了。
这个动画变形过程路径的数量差别比较大,固然了,掌握了奇淫技巧的咱们怎会被这个问题难住,悲伤的眼睛只有两段路径,而螺旋线眼睛足足有七段路径,差的五段路径让咱们万能的虚拟曲线c0,0,0,0,0,0来实现就好啦,so easy!
这里由于圈圈太多,因此描边粗细stroke-width也顺便改一下。
@keyframes deformLeft3{
0% {d:path('')} /*后面补5个c0,0,0,0,0,0*/
100%{d:path('');stroke-width:4}
}复制代码
继续日后面追加定义的动画deformLeft3咯
#left{animation:deformLeft1 1s ease backwards 1s,deformLeft2 1s ease 1s,deformLeft3 1s ease 2s forwards}复制代码
这里惟一的不一样是我加了 forwards,这个属性值对应的动画属性animation-fill-mode,用来定义结束后动画的状态,forwards为动画完成后保持最后一个属性值。
为何要添加这个属性呢?由于从一开始,咱们的眼睛和嘴巴元素在代码中是没有体现的,全凭动画属性绘制路径来添加,而眼睛的下一组动画为旋转,若是变成圈圈眼以后不定义结束后动画状态,在旋转动画时,动画元素为空。
嘴巴的变形动画也星对比较简单,只须要给表示悲伤的向下弯曲的路径增长锚点,补齐撇嘴对应的路径数量就好啦。
眼睛的旋转动画实现起来很简单,不过要定义一下旋转的中心点transform-origin,不定义为默认以画布左上角原点为中心点。
@keyframes deformLeft4{
0%{transform:rotate(0); transform-origin:}
100%{transform:rotate(360deg); transform-origin:}
}复制代码
这个值直接经过AI得到。
#mouse{animation:deformMouse1 1s ease,deformMouse2 1s ease 2s,deformMouse3 1s ease 3s forwards}复制代码
好了,以上就是所有动画的实现过程,那么作完这么一套动态变化的表情能用在什么地方呢?这就是咱们“动静分离大法”玄妙之处,你只须要改一下静态底图,就能得到各类不一样效果。并且任意改颜色,简直爽歪歪。
好比我曾经作过一组方形的表情图标,是下面这种
如今,我想让第一排第二个当心心图标变身动态表情,只要把咱们的动画效果叠加上,再经过SVG的width、height、viewBox属性值的设定进行缩放,就获得了下面这个方形表情:
其余应用就再也不一一举例了,就酱。