特别声明:本文转载@泱泱的《》一文,如需转载,烦请注明原文出处:https://juejin.im/post/5a150fc06fb9a0451e3f7042。
CSS3的动画相关的基础的属性基本都涉猎过了,个人认为,其中最复杂的是d:path()
路径变形动画,超过3D,而位移、轨迹、旋转、缩放、斜切什么的,相对简单一些,但作为非动画设计师而言,灵活的掌握这些基本的动画加以无穷无尽的变换,就已经能做出很多华丽丽的效果了,这篇呢,源于做一个练习时,AI的连续旋转复制功能,试着做了几个动效,简单、省时、高效,最主要的是用到CSS3的transform:rotate()
旋转属性,辅以位移和缩放。
最基本的旋转动画
下面这张效果图,粗通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); /*角度增加10度*/
transform-origin:400px 300px
}
}
/*动画时间增加0.2s*/
#leaf2{
animation:leaf2 ease 0.2s both;
}
所以在做动效时发现,不会JS绝对是短板,尤其在这种批量的活中,本来就是repeat的工作,用SCSS的话,$deg: $deg + (360deg / 36)
和animation: leaf#{$i} 0.2s ease both
来代替那一堆罗里吧嗦的动画定义是不是很爽,哎,不说了,不过,这个动效确实瓣瓣有些多,下面我们会简化,另外,相信我,已经试过了,别手抽的话,大概10分钟也就搞完了。现在,如果不出意外,已经能得到下面这朵绽放的花了:
似乎还不错,但仍有需要优化的地方,首先,花瓣是带透明度的,一开始未旋转时重复在相同区域,层层叠加导致透明度降低,看上去不像是旋转复制的效果,而是把一大把重叠的花瓣依次展开的效果(脑补一下赌神中一封扑克“唰”的展开的场景),如果仔细看看我们的实现过程,就是如此,那这里想要达到每一瓣都是从上一瓣的位置复制出去,怎么办,改呗。这里实现的思路也是有多种,我是用改透明度的方法。放上前三片旋转花瓣的CSS3定义和上面的对比一下(不是要罗代码,只是太少看不出规律):
@keyframes leaf1{
0%{
opacity:0; /*增加初始透明度的定义0,即初始不可见*/
transform:rotate(0deg);
transform-origin:400px 300px
}
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;
}
}
/*动画时间统一为0.1s并增加动画延迟时间的设置0.1s*/
#leaf2{
animation:leaf2 ease 0.1s both 0.1s;
}
@keyframes leaf3{
0%{
opacity:0;
transform:rotate(20deg);
transform-origin:400px 300px;
}
100%{
transform:rotate(30deg);
transform-origin:400px 300px;
}
}
/*动画延迟时间0.2s,依次类推*/
#leaf3{
animation:leaf3 ease 0.1s both 0.2s;
}
在进行一番纯体力运动后,完成了如下优化后的效果:
好了,以此为基础,来试试其他效果。(为了好做,我把花瓣数量减半了)。比如换换旋转原点transform-origin
的值,改一下颜色,就得到了下面这种:
上面效果都是单色的,没有体现设计师小伙伴们那卓越的配色效果对不对?虐心的改造来了,比如每朵花瓣单独定义颜色(对我这种毫无审美的假设计师而言只能用系统的色板取色),再随随便便换换基础图形(即<symbol>
定义的图形),就得到了下面这种蝴蝶展翅:
好啦,剩下的自己玩吧,各种形状,走起,总之,你在AI里面能实现的此类效果都可以通过这种动画方式来实现。
叠加缩放动画
嫌弃单纯的旋转复制的效果太单调?没有关系,我们来一个个叠加其他动画属性,先叠加个简单的,缩放动画。这个也是在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*1.2
、1.2*1.2*12
……需要稍微计算一下。这样我们就得到了下面这个旋转叠加缩放的复制动效:
同样,改改形状和变形的原点,可以很轻松的做出下面这种:
这里除了填充颜色不同,还稍微改了一下,用了CSS3的混合模式,增加了一个属性值mix-blend-mode:lighten
,也就是我们PS或者AI混合模式中的变亮。transform:scale()
属性与旋转不同,是支持两个值的,比如写成这种transform:scale(1,1.3)
就意味着宽度不变,高度放大1.3
倍,我改了一个三角形的看一下效果。
只是简单的示例,效果不是很好,有创意的设计师可以自行发挥,知道可以分开定义就可以啦。
叠加位移动画
有了上面关于叠加缩放动画的尝试,叠加位移动画就简单多了。看一下下面这种动效效果,这是一个很讨巧的动画。
之所以说它讨巧,是因为仔细分析动效,所有花瓣的位移都是一致的,也就是说我把位移属性设置到了所有花瓣元素的组合<g>
元素上。这样的话,我赋给组合一个位移属性设置transform:translateX(50px) translateY(50px)
,就可以实现这种效果了。关于旋转原点的定义,因为每个花瓣都是在一个动态位移的过程中,所以我把旋转原点定义为transform-origin:30% 30%
,让每个花瓣都以自己的固定的一个点为基准。
关于渐变色的配色,这里有个小技巧可以参考一下。
我们常用的色值,除了RGB
和十六进制表示方法,还有一个hsl
(色相、饱和度、明度)表示方法。如上图所示,最深色和最浅色的hsl
值获取到之后,剩下的颜色可以手动去写。
在考虑用什么来展现这种旋转复制的位移动画时,突然想到了一个高逼格的图形,鹦鹉螺的黄金螺旋!来看下下面这张图。
被复用的是一个1/4
扇形,旋转角度为-90
度(90
度为顺时针旋转),放大的比例有规律可寻,即斐波那契数列。位移值最简单的计算方法是和上一个相比较,比如图形7和图形6相比,垂直方向没有位移,水平方向正向位移为图形5的宽(高)度。因为这里transform
设置了scale
、rotate
、translate
三种属性,在书写顺序的时候,一定要把rotate
放到scale
的后面,防止因为旋转导致坐标系变化,位移值不好推算。
这样,我们就得到了一个完美黄金螺旋动效。这里我唯一不能理解的是如果不是填充而是描边属性,描边值会等比例放大。
对于此类旋转复制动画,最重要的是<symbol>
元素定义重复使用的图形,然后<use>
元素去引用。重复几次就引用几次。