相关文章推荐
卖萌的眼镜  ·  mysql ...·  11 月前    · 
绅士的鸡蛋面  ·  java hbase 读写 ...·  1 年前    · 
精彩文章免费看

SVG+CSS3 打造舞动的机械人

想法来源于codepen大神的一个神作,一群机械人以神一样的步伐在进行群魔乱舞,可是,可是,打开一看,纯js实现,js!也罢,我偏要试一下用SVG+CSS3能不能搞出这个效果来,o( ̄ヘ ̄o#)。此为前提。

1.基础图形与基础动画

先来个简易版的机械人吧,因为重点是动效,所以就简易到不能再简易,全部胶囊样式的圆角矩形来搞,但为了方便以后替换个胳膊腿什么的,我还是乖乖的把每个准备运动起来的零件都拆分到了不同的图层,并且给关节部位打了一个螺丝钉。好吧好吧,简易螺丝钉,打了个黑点行了吧,在AI里绘制完成后,这货是下面这样滴。(为了方便叠加,我给加了透明度,后来发现有透明度居然自带设计感,那就这样吧)

image

CSS部分略通一二的小伙伴都知道,再简单不过, transform:rotate 属性,这里唯一要注意的是在定义animation时,一定要定义transform-origin,旋转的原点,这里就是我在关节处打了一堆黑点的意义了。因为我AI导出的SVG中,每个关节,也就是 <circle> 的圆心 cx cy 的值,就是各个部位旋转的原点。

很好,很听话。既然动起来有了生命,管它硅基还是碳基,给“他”起个帅气的名字,叫起来也方便。大白(●—●)不能叫,那就叫小冰吧。“Hi~,我是小冰”

小冰,现在命令你动一下左腿,摆幅大一些。

image

这是?各甩各的,谁都不理谁?拜托,你们可是一个整体哎。现在的问题来了,我们CSS动画属性定义的时候,每个可活动的形状的旋转原点都是给了固定值,那既然如此,怎么才能让末肢的原点随着上肢的摆动而动起来呢?

2.SIML路径动画解决方案

凡事皆要慢慢来,先进行第一步拆解,只让上半部分肢节动起来。

为了方便查看(现在眼花缭乱的不能直视),小冰听令,先暂停摆动,右大腿带着右小腿动一个。(大腿和小腿用相同的旋转动画定义,包括原点,统一定义为大腿旋转的原点)

image

简单来说,我把需要摆动的四个末肢放到四个SVG里,还是拿右腿为例。看图,看图。小腿所在的独立的SVG先与大腿保持相同的旋转运动,当然,用的也是大腿的旋转原点O2,里面组成小腿的形状按自己坐标系的旋转原点O1运动,因为SVG运动的过程中,坐标系也在运动,所以虽然相对于原始坐标系小腿的运动的原点一直在变化,但在它自己的坐标系里,却始终不变。有点拗口,但理解了动画思路也就打通了。
贴上部分代码顺便解释一下
首先,最重要的是,放到html中,首先要把SVG的位置属性定义成绝对,这里不卖弄了,小伙伴都懂得,因为我们的SVG是互相重叠的,所以

SVG{position:absolute}

运动的CSS代码如下(只放了右腿的):

 @keyframes rightLeg{              /*定义右腿大腿的摆动(旋转动画)*/
 0%{transform:rotate(0deg); }
 100%{transform:rotate(-90deg); }
 .rightLeg{
animation:rightLeg 1s ease alternate infinite; 
transform-origin:           /*旋转原点O1*/
@keyframes rightLeg2{         /*定义右腿小腿的摆动(旋转动画)*/
0%{transform:rotate(-50deg); }
100%{transform:rotate(50deg); }
.rightLeg path{
animation:rightLeg2 0.4s ease alternate infinite ;
transform-origin:          /*旋转原点O2*/

DOM部分,大腿、胳膊肘儿、头、身体是同一个SVG,组成小腿部分是单独的SVG

<svg class="rightLeg">
<path d=""/> <!--这里可能是path,也可能是rect,总之AI导出什么就是什么啦。-->

好了,小冰,听口令,现在让大家看一下正常的机械腿。

就这样吧,拆得再散实在招架不住了。

如果你觉得身体部分一动不动,太过死板的话,no problem,先理清楚思路,首先,所有的零件一起移动,同时,大腿在自己的坐标系做旋转运动,小腿在自己的坐标系做旋转运动。这样的话,要对原DOM结构再加入一个容器<div>。把所有的SVG放到这个<div>中。
CSS部分原来的不变,增加一个身体移动部分的定义如下:

 @keyframes base{        
 0%{transform:translateX(-100px); }
 100%{transform:translateX(100px); }
.base{
animation:base 1s ease alternate infinite;

或者再增加点摆动,就得到了下面这个效果:

记得重新定义旋转原点!!

关于动效联动重点是相对坐标系的使用,也就是说,如果一个元素需要“自动”和“公动”(源自自转和公转,自己造词)方法就是放到单独的SVG中,每个SVG拥有自己独立的坐标系,组成元素的“自动”遵循自己的坐标系。

这个方法一旦掌握,再做动效时简直为所欲为,做机械臂很简单吧?做摩天轮很简单吧?感兴趣的小伙伴可以自行尝试。
另外,另外,其实我知道最好的方法是用js,比如我们这种动画,可以js去获取关节部分的坐标值,再赋值给旋转原点,可是,这不是不会嘛~~手动(* ̄︶ ̄)

最后编辑于:2017-12-11 07:46