上篇:juejin.im/post/591272…
中篇:juejin.im/post/591514…浏览器
在前面两篇文章中,虽然完整描述了任意图形的变形动画实现方法,但最大的局限性显而易见,那就是都是一个图形变造成另外一个图形,那若是是一变多或者多变一怎么实现呢?下面就来解决这个问题。bash
以最简单的例子来讲明,我要作个一个水珠裂变成两个水珠的动画效果,裂变过程毫无疑问属于图形的变形过程。可是裂变以后分开成两个的时候怎么办?这是咱们首要解决的问题。先说一下各类实现思路,而后进行对比。svg
咱们在前面说过用剪刀断开锚点,使闭合路径转换成开放路径,因此聪明的设计师小伙伴应该能够想到,既然能够断开一个锚点,那就能够再断开一个,让一条路径变成两条路径,两条路径分别实现本身的动画效果,换句话说,就是半个小水珠变成一个小水珠的变形动画,以下图所示工具
<path>
各调用一个变形动画,代码以下:
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*变形前左半个水滴的路径*/
100% {d:path('');} /*变形后左边水滴的路径*/
}
@keyframes deform2{
0% {d:path('');} /*变形前右半个水滴的路径*/
100% {d:path('');} /*变形后右边水滴的路径*/
}
#animate1 {animation: deform1 2s ease;}
#animate2 {animation: deform2 2s ease;}
</style>
<path id="animate1"/>
<path id="animate2"/>
</svg>复制代码
那看一下这种实现思路获得的效果如何post
虽然表面上看实现了1变2,但一分为二的过程极其生硬,主要缘由是咱们实现思路就是半个水滴到一个水滴,因此动画过程彻底复现了咱们的思路。优化
上面方法实现的效果并很差,并且设想一下,这是变成2个,那若是是变成3个,4个呢,要把变形前的图形切的稀碎么……
既然咱们前面两篇都是一变一的实现方法,那么咱们不妨变通一下,好比变形前的水滴实际上有两个彻底重合的图形,一个变成左边的,一个变成右边的。实现思路以下:动画
虽然两个水滴是重合的,可是路径方向那里,向左变形和向右变形的原始路径方向必定要是相反的,不然你将获得下面这种效果(你甭说,就这种误打误撞的错误效果,作个打开的门啊,书啊的,竟然还不错):url
先不要把这个方法一棍子打死,那是由于咱们变形先后的图形形状没有变化,才会产生位移效果,若是是作一个圆形变成两个水滴,变形效果仍是有的,以下:spa
效果一点都不欢乐,直接暴露了咱们妄图掩盖的事实真相。
固然了,方法2虽然不是最佳,但某些情景下也是适用的。
不过咱们重磅推出的是下面这个方法。设计
此方法堪称方法1和方法2的结合,咱们方法1是把原始形状生生的切成两半,那这个方法是咱们找变形后图形一分为二的那一瞬间,好比针对这个变形效果,就是两个变形后水滴仍然相连的刹那,此时,仍然是一个图形,动画分解成两个阶段,第一阶段,藕断丝连,第二阶段,快刀斩下。但在瞬间,运用了“障眼法”,来实现两个过程的完美拼接。
那咱们要作的,就是在AI里用路径查找器,把临界点的两个形状进行合并。我用图示表示一下
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*原始水滴*/
100% {d:path('');}/*临界点水滴*/
}
@keyframes deform2{
0% {d:path('');} /*重叠效果的左边水滴*/
100% {d:path('');} /*移动位置后的左边水滴*/
}
@keyframes deform3{
0% {d:path('');} /*重叠效果的右边水滴*/
100% {d:path('');} /*移动位置后的右边水滴*/
}
#animate1 {animation: deform1 1.5s cubic-bezier(0.8, 0, 0.85,0.5);}
#animate2 {animation: deform2 0.5s cubic-bezier(0.15, 0.5, 0.2, 1) 1.5s;}
#animate3 {animation: deform3 0.5s cubic-bezier(0.15, 0.5, 0.2, 1) 1.5s;}
</style>
<path id="animate1"/>
<path id="animate2"/>
<path id="animate3"/>
</svg>复制代码
简单解释一下,2s的动画效果我拆分红2部分,前一部分变形效果1.5s,第二部分位移0.5s,但要延迟1.5s后执行,以实现时间上的无缝对接。
修改运动速率,是由于ease表示慢-快-慢,若是拼接动画都使用这个运动速率,整个流程下来就是慢-快-慢-慢-快-慢,在临界点那里会有明显的停顿感,所以我修正了运动速率以消除停顿效果。原本用了预约义的值,变形动画为ease-in(慢—快),而位移动画为ease-out(快-慢)。但发现衔接部分仍然不够顺滑,索性本身从新写了速率曲线,说着吓人,方法掌握以后其实很简单,正好借这个案例说一下:
来看下效果如何:
小总结,之因此没有从一开始就直接来方法3,是由于方法3费时最长,其实咱们须要的是越简单的方法实现越理想的效果越好(拗口),因此在一些场景中,能用方法1和方法2(尤为方便)来实现实则再好不过。
对于方法3这种寻找临界点的图形,则更适合精细化制做。
小技巧:因为这类变形动画涉及的形状及位置比较多,为了方便本身查看SVG代码,实际展示的色值信息因为是定义在CSS样式中,因此建议做图时定义成方便识别的颜色,或者建在不一样图层上,(AI导出的SVG会根据不一样图层进行分组)。
截止到这里,咱们已经能够实现无穷的变形效果了,裂变,组合,玩到嗨起来。但还有一种常见的图形,须要单独说一下实现变形动画的方法,就是下面这种镂空的图形,此次的案例是从一把钥匙变成一把锁,只须要这一个案例作基础,掌握方法以后,一通百通,原始图片以下:
若是没有钥匙孔和锁孔,这种变形动画实现起来可谓简单无比,但多了孔以后,貌似有点棘手,别急,先来看这种图形(AI中须要合并形状)d值的面目。因为案例图形太过复杂,咱们仍是从最简单的入手。
这里借用之前提到的蒙版来试一下。
UI设计师对于蒙版丝绝不陌生,SVG蒙版的原理是同样的,镂空部分我用黑色蒙版来处理,达到一样的效果。
思路以下:动画拆解成两部分,一部分是无镂空部分的图形的变形动画,另外一部分我把变形动画附加给蒙版黑色部分,即咱们要镂空的区域。
<svg>
<style>
@keyframes deform1{
0% {d:path('');}/*变形前底图*/
100% {d:path('');}/*变形后底图*/
}
@keyframes deform2{
0% {d:path('');}/*变形前蒙版黑色部分*/
100% {d:path('');/*变形后蒙版黑色部分*/
}
}
#animate1 {animation: deform1 3s ease;}/*
底图变形动画*/
#animate2 {animation: deform2 3s ease ;fill:#000000;}/*
蒙版黑色区域变形动画*/
</style>
<mask id="hollow"><rect x="0" y="0" fill="#ffffff" width="" height=""/><path id="animate2" /></mask><!--定义一个白色矩形为底,黑色为变形动画的蒙版hollow-->
<path id="animate1" mask="url(#hollow)"/><!--底图变形动画上附加一个蒙版变形动画-->
</svg>复制代码
看到这里,没有任何SVG蒙版基础的UI设计师或许会有些发憷,但仍是但愿了解一下,由于蒙版动画很强大,后面会开单独的专题。
来看一下利用蒙版变形结合底图变形的动画效果如何:
前面提到过,把蒙版动画单独定义自由度更高,好比,我再给蒙版变形动画增长一个50%的关键帧,而后缩小成极小的一个点,动画效果就变成了下面这种:
咱们对图形的操做一直说的都是锚点手柄部分处理,一直想避开这部分,主要是考虑到UI设计师毕竟对AI软件更熟悉,操做起来更方便,而是我在作案例的实际操做过程当中,发现对于锚点较少的状况还好,找对应路径也能顺利找到,而在我上面钥匙和锁变形动画中(20个锚点),即便经过d值看出来有些曲线时非小c开头的,但数起来真的很困难,因此额外增长这一部分,能够直接经过修改d值实现同一成小c曲线转换的方法。只说方法,不说原理哦。
先说最容易出现的小s,看过上篇的设计师们已经知道产生小s的方法是由于转换点直接拖拽,并且s后面只有四个值,转化方法以下:
sA,B,C,D←→c前一组倒数第二个数减去倒数第四个数,前一组倒数第一个数减去前一组倒数第三个数,A,B,C,D
啊啊啊,头晕了对不对,这仍是仅限于前面是正常一组小c开头的曲线的转换公式,因此除非你只有极个别小s出现,不然多算伤身啊。
设计师小伙伴们必定擦亮眼睛,由于小l与数字1太像,但只要记得咱们的d值只支持一位小数,而出现相似3.51这样的数据时,那必定是3.5和小l。小l是绘制直线的命令,后面只有两个值,转换方法以下:
lA,B←→c0,0,A,B,A,B
前面补两个0,后面复制一组小l后面的两个值。
小l和小s最多见,下面这两个则出现的状况少一些,一点出现,建议改一下图形,为什么,来看转化方法。
h为水平直线绘制命令,后面只有一个值,转换方法以下:
hA←→c0,0,A,前一组路径曲线小c的最后一个值,A,前一组路径曲线小c的最后一个值
v为垂直直线绘制命令,同上同理,转换方法以下:
vA←→c0,0,前一组路径曲线小c的倒数第二个值,A,前一组路径曲线小c的倒数第二个值,A
看,诚不欺你,因此为了避免给本身制造困难,稍微挪挪锚点,不要那么水平垂直的直来直去嘛。
还有出现的状况是绝对定位大写字母开头的,这个转换起来,啧啧,反正不借助工具,我是不能接受手动计算的。
就酱。
借助公式,顺便作个动画效果看看。
d:path('M60,490,c0,0,50,0,50,0,c0,0,100,0,100,0,c0,0,50,0,50,0,c0,0,50,0,50,0,c0,0,50,0,50,0,c0,0,50,0,50,0')复制代码
这就是相对坐标的好处,c0,0,50,0,50,0,表示一根水平的宽度50的直线,对应蘑菇的6段曲线,重复6次就OK了。
再来一根直线变飞鸟与鱼的,哦,不是飞鸟,是肥鸟。把前面的知识点借机再唠叨一遍。顺便带出来压箱底的技能,虚拟曲线。先卖个关子。
d:path('M40,130,c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,280,0,280');复制代码
其实这个效果和
d:path('M40,130,c0,0,0,280,0,280');复制代码
是同样的,咱们只是在欺骗浏览器,制造一些不存在的曲线以便弥补变形先后图形曲线数量的不一样。
动画能够拆成两部分,衔接起来,也能够像我这样在一个动画里完成,因为最终小胖鸟的曲线数量最多,多以最终我给直线补充了8段虚拟曲线,给小鱼补充了5段(所有放到鱼嘴的位置),而后看一下效果
是否是感受太简单了,并且很愤怒的指出来,为何到最后才说这种简单好用的方法?!勿燥,理由很简单,加锚点是为了让变形的过程变得均匀。好比个人小鸟变成鱼,若是是经过分散添加锚点来实现,效果是下面这样的:
d:path('M60,490c0,0,150,0,150,0c0,0,150,0,150,0')复制代码
而后把须要增长的4条虚拟曲线塞进去,位置就是中心点,也就是第一段路径后面。
d:path('M60,490c0,0,150,0,150,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,150,0,150,0')复制代码
好了,看看是否是从中心点长出的蘑菇:
svg描边动画效果在别的文章里介绍过,利用路径变形动画依旧能够完成,只不过这只是种“伪描边”,更像是从某个点辐射出去的效果,看一下下面这个动画:
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*花茎变形前虚拟点*/
100% {d:path('');}/*花茎曲线路径*/
}
@keyframes deform2{
0% {d:path('');}/*左边叶子变形前虚拟点*/
100% {d:path('');}/*左边叶子曲线路径*/
}
@keyframes deform3{
0% {d:path('');}/*右边叶子变形前虚拟点*/
100% {d:path('');}/*右边叶子曲线路径*/
}
@keyframes deform4{
0% {d:path('');}/*花朵变形前虚拟点*/
100% {d:path('');}/*花朵曲线路径*/
}
#animate1 {animation: deform1 1s ease forwards;}/*长出花茎时间1s,forwards表示动画状态停留在结束状态*/
#animate2 {animation: deform2 1s ease 1s forwards;}/*长出左边叶子时间1s,延迟1s(即花茎动画时间)开始*/
#animate3 {animation: deform3 1s ease 2s forwards;}/*长出右边叶子时间1s,延迟2s(即花茎+左边叶子动画时间)开始*/
#animate4 {animation: deform4 1s ease 3s forwards;}/*开花时间1s,延迟3s(即花茎+左边+右边叶子动画时间)开始*/
</style>
<path id="animate1"/>
<path id="animate2"/>
<path id="animate3"/>
<path id="animate4"/>
</svg>复制代码
这里再提供一个转换方法,就是关于绝对位置大C绘制路径。若是你导出的d值中有大C开头的曲线,关于这种经过虚拟点变形的话,就没有必要再去调整路径了。
c0,0,0,0,0,0等同于CX1,Y1,X1,Y1,X1,Y1。X1和Y1就是你的起始点M值的坐标。关于SVG路径path的贝塞尔曲线绘制方法的介绍网上不少,耐心看一遍就知道转换的缘由了。
实际使用过程当中,必定要把握的思路是尽可能用最简单的方法来实现动效,已经开始着手准备写一篇SVG微动效的文章,毕竟SVG结合CSS3实现的动画不可与真正的动画制做软件同日而语,应用最多的场景,应该是一些微动效。这篇做为变形动画的进阶篇,涉及的知识点比较杂,包括拼接动画临界点的定义及自定义速率曲线实现无缝拼接的方法,结合蒙版变形动画实现变形动画,非小c开头的路径曲线的转化,添加虚拟曲线。变形动画全篇终。有问题单独留言。