SVG+CSS3 打造舞动的机械人

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

1.基础图形与基础动画

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

image

虽然没有科技感,且遍布全身的诡异黑点导致它看上去像是十八铜人或者中医针灸啊穴位啊的什么东西,但是这不妨碍我们的机械人运动,来吧,给大家打个招呼,动动头先,走起来。

image

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

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

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

image

好的,接下来,其他部位一并动起来。

image

好了检测完毕,一切正常。等等,似乎哪里不太对,聪明如你一定发现了诡异之处,那就是——动效里都是肢体的末节在动,小腿动大腿不动,胳膊动胳膊肘不动,咳咳,是的,这是一个被钉住只能挣扎的机械人。钉住小冰的就是那一堆“螺丝”。为什么这么搞呢?理由很简单,我让大腿动一下,看看发生了什么

image

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

2.SIML路径动画解决方案

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

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

image

有没有毛病?有!不符合物理规律的样子。我们先用图来分析一下,然后来对症下药。

image

大腿从位置A甩到位置B,我希望得到小腿的效果是始终保持下垂。相当于小腿部分没有摆幅度的运动,也就是沿着图中的虚线轨迹运动。等等,想起来了点什么没?轨迹?我们在路径动画中提到过是可用控制摆动的,<animateMotion rotate="auto">这是定义随着路径摆动,不定义的话默认不摆动,那既然圆形也可以是路径,我们这里用路径动画实现一下看看如何。关于路径动画的详解我以前写过详解了,这里只看效果:

image

似乎解决了问题的样子。但是,新的问题已然出现,就是我要甩大腿的过程中小腿自然摆动,怎么搞?

3.拆解SVG,利用独立坐标系解决方案

去他的路径动画,正解在这里,因为一个SVG是一个坐标系,也就是说我们定义旋转原点的时候都要遵循同一个规则,在立方体旋转动画里,我们曾经搞过,六个面,六个SVG,里面各自动画进行,互不干扰,这个思路放到我们这个动画中,依旧可行。

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导出什么就是什么啦。-->
</svg>

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

image

perfect!现在小腿和大腿可以无缝连接在一起,想怎么动就怎么动,运动速度啊,摆动幅度啊,任意定义。

剩下的又是体力活了,现在把其余的部分按照上面的思路拆解就可以咯。我随随便便定义了一下(说是随便,但每个都要定义一堆,也是头昏脑涨啊),然后就得到了下面这段动画。

image

机械舞,够不够魔性。
当然了,如果你有足够的创意的话,可以随便玩儿嘛,反正小冰非我族类,怎么运动都可以。比如齐刷刷的左右摆动(左臂右臂定义成相同的动画,左腿和右腿定义成相同的动画)

image

总之,怎么定义都行,一切随意。

还记不记得我们的跳帧动画,见这篇文章https://juejin.im/post/597694e75188250d4d352cf9
里面做了一些效果,比如“咔哒咔哒”的时钟,我们的小冰也可以“咔吧咔吧”的动起来。在定义动画animation时,去掉ease啊,linear啊,或者cubic-brazier这些定义速率的值,换成steps(),就会得到缺少润滑油的小冰,关于steps(n)里n值的定义,可以不要太过随意,根据旋转动画的时间,使咔吧的频率保持一致,会更严谨一些。我做了效果可以看一下:

image

再比如我们来个炫酷的组装过程。(动画第一部分为零件组装,也就是以transform:translate位移动画为主)

image

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

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

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

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

image

在基础的动效基础上,可以对机械人小冰进行各种美化,去替换SVG的组成部分就可以,比如下面这种:

image

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 先看一个动画效果,这种小飞机沿路径飞行(路径部分线段变成绿色是录屏软件出了问题)。 这种动画效果最常见于发送信息后...
    泱泱悲秋阅读 3,944评论 3 11
  • 1、属性选择器:id选择器 # 通过id 来选择类名选择器 . 通过类名来选择属性选择器 ...
    Yuann阅读 1,513评论 0 7
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • 首先把基础效果放上,一个动态缩放的圆形。 这是一个模板,里面的代码可以直接复用,并可以延伸出一系列效果,主要是为了...
    泱泱悲秋阅读 2,477评论 0 7
  • 苍天饶过谁 大周末上课啊绝望 … 学会坦然接受命运的安排 三年没见的同学来西大 带她们去吃了鸡公煲 哎呀北京回来的...
    珍惜眼前始为真阅读 116评论 0 1