不炫技,SVG+CSS3 旋转动画属性就能实现的梦幻效果

15,216 阅读8分钟

CSS3的动画相关的基础的属性基本都涉猎过了,个人认为,其中最复杂的是d:path()路径变形动画,超过3D,而位移、轨迹、旋转、缩放、斜切什么的,相对简单一些,但作为非动画设计师而言,灵活的掌握这些基本的动画加以无穷无尽的变换,就已经能做出很多华丽丽的效果了,这篇呢,源于做一个练习时,AI的连续旋转复制功能,试着做了几个动效,简单、省时、高效,最主要的是用到CSS3的transform:rotate()旋转属性,辅以位移和缩放。

1.最基本的旋转动画

下面这张效果图,粗通AI的设计师小伙伴们一定都不会陌生,在AI里面就是ctrl+D连续复制的体力活。

单色选择复制效果
如果把连续旋转复制转成CSS3语言,也是极简单的。来分析一下上面的图形,我做的时候每次旋转的角度为10度,就意味着有36朵花瓣,那对应SVG里应该有36个路径<path>,如果是AI直接导出的SVG看一下代码,也是密密麻麻的罗列,因为都是相同的形状,自然有简单的方法来实现,只需定义一个被重复使用的图形,有两种方法<defs>元素和<symbol>元素来定义,<use>元素来引用,那因为<symbol>元素使用范围更宽泛一些,所以我们需要的工作就简化成,在AI里做一片花瓣的基础图形,然后导出路径后,定义如下

 <symbol id="single">
 <path d=""/> <!--此处为AI导出的单片花瓣的路径-->
 </symbol>

先来第二片花瓣(也就是第一个旋转的花瓣),CSS部分定义如下:

@keyframes leaf1{
0%{transform:rotate(0deg); transform-origin:400px 300px}
100%{transform:rotate(10deg); transform-origin:400px 300px}
}
#petal1{animation:leaf1 ease 0.1s both;}

DOM部分,只需要用<use>元素引用定义好的花瓣并且赋给它旋转的动效就可以了。

好了,剩下的还是体力活,需要把<use>元素部分复制34次,然后CSS动画部分复制34次,当然了,动画那里,需要递增一下时间和旋转角度,比如接下来那片花瓣<use id="leaf2" xlink:href="#single"/>对应如下动画属性:

 @keyframes leaf2{
 0%{transform:rotate(0deg); transform-origin:400px 300px}
 100%{transform:rotate(20deg); transform-origin:400px 300px} /*角度增加10度*/
 }
 #leaf2{animation:leaf2 ease 0.2s both;} /*动画时间增加0.2s*/

所以在做动效时发现,不会js绝对是短板,尤其在这种批量的活中,本来就是repeat的工作,用SCSS的话,$deg: $deg + (360deg / 36)animation: leaf#{$i} 0.2s ease both来代替那一堆罗里吧嗦的动画定义是不是很爽,哎,不说了,不过,这个动效确实瓣瓣有些多,下面我们会简化,另外,相信我,已经试过了,别手抽的话,大概10分钟也就搞完了。现在,如果不出意外,已经能得到下面这朵绽放的花了

似乎还不错,但仍有需要优化的地方,首先,花瓣是带透明度的,一开始未旋转时重复在相同区域,层层叠加导致透明度降低,看上去不像是旋转复制的效果,而是把一大把重叠的花瓣依次展开的效果(脑补一下赌神中一封扑克“唰”的展开的场景),如果仔细看看我们的实现过程,就是如此,那这里想要达到每一瓣都是从上一瓣的位置复制出去,怎么办,改呗。这里实现的思路也是有多种,我是用改透明度的方法。放上前三片旋转花瓣的CSS3定义和上面的对比一下(不是要罗代码,只是太少看不出规律):

 @keyframes leaf1{
 0%{opacity:0; transform:rotate(0deg); transform-origin:400px 300px} /*增加初始透明度的定义0,即初始不可见*/
 100%{transform:rotate(10deg); transform-origin:400px 300px}
 }
 #leaf1{animation:leaf1 ease 0.1s both ; }

 @keyframes leaf2{
 0%{opacity:0; transform:rotate(10deg); transform-origin:400px 300px} /*增加初始位置定义,即上一朵花瓣的位置*/
 100%{transform:rotate(20deg); transform-origin:400px 300px} 
 }
 #leaf2{animation:leaf2 ease 0.1s both 0.1s; } /*动画时间统一为0.1s并增加动画延迟时间的设置0.1s*/

@keyframes leaf3{
0%{opacity:0; transform:rotate(20deg); transform-origin:400px 300px}
100%{transform:rotate(30deg); transform-origin:400px 300px}
}
#leaf3{animation:leaf3 ease 0.1s both 0.2s;} /*动画延迟时间0.2s,依次类推*/

在进行一番纯体力运动后,完成了如下优化后的效果:

好了,以此为基础,来试试其他效果。(为了好做,我把花瓣数量减半了)。比如换换旋转原点transform-origin的值,改一下颜色,就得到了下面这种:

上面效果都是单色的,没有体现设计师小伙伴们那卓越的配色效果对不对?虐心的改造来了,比如每朵花瓣单独定义颜色(对我这种毫无审美的假设计师而言只能用系统的色板取色),再随随便便换换基础图形(即<symbol>定义的图形),就得到了下面这种蝴蝶展翅:

身无彩凤双飞翼

好啦,剩下的自己玩吧,各种形状,走起,总之,你在AI里面能实现的此类效果都可以通过这种动画方式来实现。

2.叠加缩放动画

嫌弃单纯的旋转复制的效果太单调?没有关系,我们来一个个叠加其他动画属性,先叠加个简单的,缩放动画。这个也是在AI中常用的功能之一,缩放和旋转操作后,反复的ctrl+D来复制操作。看下下面这张图,解析一下

单色缩放旋转复制
不过是最里面的圆角矩形先等比例放大后旋转一个固定角度,后面的依次重复这种变换,缩放+旋转→复制,那我们来转成CSS3属性。 基于上面的基础,首先把<symbol>定义的基础图形改一下,旋转的那里不用管,现在要增加一个缩放的属性scale()设置。比如在这个例子里,我缩放是按1.2倍来进行的,以第一个进行变化的图形为例,CSS属性定义如下:

@keyframes leaf1{
0%{opacity:0; transform:rotate(0deg); transform-origin:400px 300px}
100%{transform:rotate(30deg) scale(1.2); transform-origin:400px 300px} /*增加缩放的比例设置*/
}

这里比旋转变形略复杂的在于比例的计算,不像角度那样可以30度60度90度……直接叠加,缩放比例则是1.2、1.2*12.、1.2*1.2*12……需要稍微计算一下。这样我们就得到了下面这个旋转叠加缩放的复制动效:

同样,改改形状和变形的原点,可以很轻松的做出下面这种

这里除了填充颜色不同,还稍微改了一下,用了CSS3的混合模式,增加了一个属性值mix-blend-mode:lighten,也就是我们PS或者AI混合模式中的变亮。 transform:scale()属性与旋转不同,是支持两个值的,比如写成这种transform:scale(1,1.3)就意味着宽度不变,高度放大1.3倍,我改了一个三角形的看一下效果。

只是简单的示例,效果不是很好,有创意的设计师可以自行发挥,知道可以分开定义就可以啦。

3.叠加位移动画

有了上面关于叠加缩放动画的尝试,叠加位移动画就简单多了。看一下下面这种动效效果,这是一个很讨巧的动画。

位移旋转复制动画
之所以说它讨巧,是因为仔细分析动效,所有花瓣的位移都是一致的,也就是说我把位移属性设置到了所有花瓣元素的组合<g>元素上。这样的话,我赋给组合一个位移属性设置transform:translateX(50px) translateY(50px),就可以实现这种效果了。关于旋转原点的定义,因为每个花瓣都是在一个动态位移的过程中,所以我把旋转原点定义为transform-origin:30% 30%,让每个花瓣都以自己的固定的一个点为基准。

旋转原点

关于渐变色的配色,这里有个小技巧可以参考一下。

渐变色
我们常用的色值,除了RGB和十六进制表示方法,还有一个hsl(色相、饱和度、明度)表示方法。如上图所示,最深色和最浅色的hsl值获取到之后,剩下的颜色可以手动去写。

在考虑用什么来展现这种旋转复制的位移动画时,突然想到了一个高逼格的图形,鹦鹉螺的黄金螺旋!来看下下面这张图。

黄金螺旋

被复用的是一个1/4扇形,旋转角度为-90度(90度为顺时针旋转),放大的比例有规律可寻,即斐波那契数列。位移值最简单的计算方法是和上一个相比较,比如图形7和图形6相比,垂直方向没有位移,水平方向正向位移为图形5的宽(高)度。 **因为这里transform设置了scalerotatetranslate三种属性,在书写顺序的时候,一定要把rotate放到scale**的后面,防止因为旋转导致坐标系变化,位移值不好推算。

黄金螺旋
这样,我们就得到了一个完美黄金螺旋动效。这里我唯一不能理解的是如果不是填充而是描边属性,描边值会等比例放大。

对于此类旋转复制动画,最重要的是<symbol>元素定义重复使用的图形,然后<use>元素去引用。重复几次就引用几次。