首先把基础效果放上,一个动态缩放的圆形。
这是一个模板,里面的代码可以直接复用,并可以延伸出一系列效果,主要是为了方便UI设计师只需要通过AI生成的SVG文件直接进行内容替换,让不会CSS3动画属性的UI也能轻松的实现类似的动画效果。
以后会陆续更新针对UI设计师的这种SVG动画教程,宗旨在于打破代码壁垒,让UI设计师专注于创意与设计。我会把代码尽量标准化,只需要“拷贝-粘贴”就能实现一些不错的动画效果。
先来说一下如何实现,如果学过一点点的SVG的小伙伴们,基础图形的绘制并非难事,直接可以码出circle以及cx,cy,r,fill等参数值,但对于零代码基础的UI来说,我们需要的只是在AI中建一个画布,画一个圆。
看过我的其他文章的小伙伴们应该知道,AI的画布大小对应SVG 的viewBox属性的值,关于viewBox的坐标系作用解释起来还蛮复杂,我们不如就理解成画布容器吧,所有的图形都是放到这个画布上面的。这个动画我是让整个SVG来进行缩放,所以你的圆的大小和画布大小不重要,反而在画布的位置和最终的比例决定了最终动画效果。(有点迷糊的话后面会有解释)换句话说,这里你想建多大的画布都可以,只要里面的图形元素所占的比例协调就可以了(不能太大超出画布,最大100%,也不要太小,会留出太多边距。)
把AI生成的SVG代码copy出来,删掉冗余部分,会得到下面这个代码:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
<circle fill="#FFD4A9" cx="100" cy="100" r="75"/>
</svg>
现在预览的效果是一个静态的圆形,接下来我们用到CSS3的动画属性让整个圆形动起来。我定义一个动画CSS代码如下:
@keyframes changeScale{
0% { width:100px;height:100px; top:110px; left:110px;}
50% { width:200px;height:200px;top:60px; left:60px}
100% {width:300px;height:300px;top:10px; left:10px}
}
svg{
position:absolute;
animation:changeScale 1s ease 0s infinite alternate; }
下面我们会用一张图来解释这个动画的原理以及对应的值在实际应用中如何设定。
@keyframes定义了整个缩放动画时间轴的几个关键帧,初始0%,结束100%,这两个值是不可缺少的,中间我加了一个50%,也就是我们的圆形缩放时中间停顿了一下的效果。
为了不让最终效果紧贴浏览器边缘,我通过top值和left值的设定留出了边距。
而我们之所以经过精确计算,目的则是为了让SVG(并非里面的圆形)的中心点可以重合,最终实现完美的缩放效果。
中间添加的关键帧可以有很多,比如你可以按顺序写10%,25%,60%……随便定义。也可以没有,则平滑的缩放,没有停顿效果。
简单解释一下SVG调用的动画animation:changeScale 1s ease 0s infinite alternate;每个属性的释义。changeScale为我们定义的动画名称,1s是完成一个动画效果的时间,ease为动效速度曲线, 0s表示没有延迟直接开始,infinite 表示动画无限循环播放, alternate表示一个周期动画完成后(对应的我们为SVG由初始的100*100放大到300*300)逆向播放效果(300*300再收缩到100*100)从而实现连贯性。(因为每个属性值都有很多不同的设定,有需要其他效果不明白的小伙伴们也可以直接留言)。
下面放上完整的代码,小伙伴们直接copy下来保存一个SVG文件看看效果。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
<style>
@keyframes changeScale{
0% { width:100px;height:100px; top:110px; left:110px;}
50% { width:200px;height:200px;top:60px; left:60px}
100% {width:300px;height:300px;top:10px; left:10px}
}
svg{position:absolute;animation:changeScale 1s ease 0s infinite alternate; }
</style>
<circle fill="#FFD4A9" cx="100" cy="100" r="75"/>/*这里是替换任意形状的部分*/
</svg>
这里再多解释一下刚才用AI新建画布和绘图时的问题,当你重新建一个放大一倍400*400的画布,等比例画一个300*300的圆时
SVG代码如下
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" >
<circle fill="#FFD4A9" cx="200" cy="200" r="150"/>
</svg>
但最终动画效果里的尺寸完全没有变化。
反而如果你建一个很小的画布,比如50/50,但画一个圆形50/50,充满画布,SVG代码如下
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" >
<circle fill="#FFD4A9" cx="25" cy="25" r="25"/>
</svg>
最终动画效果反而圆形变大了。效果不再放上了,可以自己却替换看一下。
就是因为我们是对SVG的尺寸进行了缩放。决定SVG尺寸的是设定的SVG的width和height的值。
SVG的width和height值设定是你真正的动画效果里图形的尺寸。
为了保证辐射状的缩放效果,要通过设定不同的位置确保缩放的SVG的中心点重合,即**left的差值=1/2width差值 top的差值=1/2height差值 **,这与SVG里包含了什么图形元素无关。
既然说了,这个是缩放动画的模板,那下面就来看一下如何套用这个模板以及还能实现什么不同的效果。
1.缩放同时颜色改变###
先看下面这种效果,星星缩放的同时伴随透明度的改变
在模板基础上需要修改的有两个部分,一个是用星星替换圆形,一个是增加一个改变透明度的动画。还是在200*200画布,我用AI自带的星形工具绘制一个星星(懒癌发作,不想做复杂的图形 o(╯□╰)o),然后AI生成SVG的代码里面,只需要<polygon>这一部分,用它去替换模板里的<circle>。
这样替换完成之后,我们就得到了一个会同样动效的星星,但为了改变透明度,我需要再增加一个改变透明度的动画,我定义为changeColor,关键帧与缩放动画的关键帧保持同步,但定义了透明度fill-opacity的变化值,最后代码如下:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
<style>
@keyframes changeScale{
0% { width:100px;height:100px; top:110px; left:110px;}
50% { width:200px;height:200px;top:60px; left:60px}
100% {width:300px;height:300px;top:10px; left:10px}
}
/*以下为改变透明度的动画设置*/
@keyframes changeColor{
0% {fill-opacity:1}
50% {fill-opacity:0.75}
100% {fill-opacity:0.5}
}
svg{position:absolute;animation:changeScale 1s ease 0s infinite alternate; }
/*让星星去调用改变透明度的动画,其他动画属性设置保持一致*/
#polygon{fill:#d95470;animation:changeColor 1s ease 0s infinite alternate;}
</style>
<polygon id="polygon" points="100,21.4 125.5,73.1 182.7,81.4 141.3,121.7 151.1,178.6 100,151.8 48.9,178.6 58.7,121.7
17.3,81.4 74.5,73.1 "/>
</svg>
这是透明度的改变,当然,也可以定义颜色的改变。比如我用AI自带的极坐标工具,乱七八糟的SVG代码不用管,我把改变颜色的动画重新定义
@keyframes changeColor{
0% {stroke:#D8645B}
50% {stroke:#5CD6C2}
100% {stroke:#8D5ED3}
}
然后就得到了下面这种效果:
2.缩放同时旋转###
继续用AI自带的螺旋线形状,生成<path>。这里我改了一下,为了让旋转看起来更顺畅,我去掉了50%关键帧,把运动速率由ease(慢-快-慢)改成了线性linear,并且去掉了旋转效果的逆向播放(删除alternate),始终保持同一个方向的旋转,得到下面的效果。
对应代码如下:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
<style>
@keyframes changeScale{
0% { width:100px;height:100px; top:110px; left:110px;}
100% {width:300px;height:300px;top:10px; left:10px}
}
@keyframes rotate{
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
svg{
animation:changeScale 1s linear 0s infinite alternate;
position:absolute;
}
#helix{
transform-origin:50% 50%;
animation:rotate 1s linear 0s infinite;
}
</style>
<path id="helix" fill="none" stroke="#58BA8E" stroke-width="10" stroke-linecap="round" stroke-miterlimit="10" d="M182.5,151.3
c-39.1,39.1-102.4,39.1-141.5,0C9.7,120.1,9.7,69.4,41,38.1c25-25,65.5-25,90.5,0c20,20,20,52.4,0,72.4c-16,16-41.9,16-57.9,0
c-12.8-12.8-12.8-33.6,0-46.4c10.2-10.2,26.8-10.2,37.1,0c8.2,8.2,8.2,21.5,0,29.7c-6.6,6.6-17.2,6.6-23.7,0c-5.2-5.2-5.2-13.7,0-19
"/>
</svg>
这里利用transform: rotate(对应旋转角度)属性定义了一个旋转动画
@keyframes rotate{
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
在定义旋转动画时,一定要定义旋转中心点,transform-origin:,这里我定义了50% 50%,即图形的中心位置,如果不定义的话会默认旋转中心点为左上角。
3.缩放复杂图形###
有点心虚的说,说是复杂,其实还是很简单的拼了个图案出来,只是为了说明用这个模板怎么来实现你想绘制的各种图案的动画,我是抛砖引玉嘛,身为UI设计师的你可以用AI随意绘制。
我画了一朵描边的云和一个月亮,这个在AI里面导出SVG的时候是两个路径<path>。
用模板来实现简直太简单了,比上面改变透明度的还要简单,只需要一个简单的替换,代码如下:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
<style>
@keyframes changeScale{
0% { width:100px;height:100px; top:110px; left:110px;}
50% { width:200px;height:200px;top:60px; left:60px}
100% {width:300px;height:300px;top:10px; left:10px}
}
svg{position:absolute;animation:changeScale 1s ease 0s infinite alternate; }
</style>
/*下面是AI生成的,直接copy就可以*/
<path fill="#D4FDFF" stroke="#29CDFF" stroke-width="4" stroke-miterlimit="10" d="M136.3,89.8c-3.8,0-7.5,0.6-10.9,1.8
C120,74.4,104,62,85.1,62C62,62,43.3,80.6,43,103.6c-14.2,1.3-25.3,13.2-25.3,27.7c0,15.3,12.4,27.8,27.8,27.8v0h89.3
c0.5,0,1.1,0,1.6,0c19.2,0,34.7-15.5,34.7-34.7C171,105.4,155.5,89.8,136.3,89.8z"/>
<path fill="#FFDC6E" d="M171.4,20.1c2.1,3,3.5,6.5,4.1,10.3c2.1,13.6-7.2,26.4-20.8,28.5c-4.8,0.8-9.5,0.1-13.7-1.7
c5.3,7.6,14.6,12,24.4,10.5c13.6-2.1,22.9-14.9,20.8-28.5C184.8,30.4,179,23.4,171.4,20.1z"/>
</svg>
4.不同效果叠加###
有了上面的基础,可以放个大招了,来实现一个多种动画叠加的效果,如下图(不要说丑,也做了很久呢):
动画其实可以拆成三部分,一部分是慢慢变大的树,我把它用我们的缩放模板来完成,不过个别参数修改了一下;一部分是沿着轨迹运动的太阳(太阳直接借用的素材,轨迹路径是自己建的);一部分是静止的小房子(直接借用的素材)。
因为不止用了一个SVG,所以我把这些放进一个html文件。先从位置示意图分析一下各种参数的设置。
先来说树,与我们前面的辐射形状缩放的动画不同,我们需要它从水平线变大,缩放的中心点已经在上图中标注了。尺寸我希望从50*50放大到300*300(图上蓝色框出的区域)。这意味着需要重新定义初始和结束的位置值,依旧在浏览器视窗边缘留出一定的距离(20px)。
绘制树的画板我们前面说过了,尺寸任意,不影响效果。这棵树熟悉AI的设计师们一定很眼熟吧,是的,这就是AI自带的符号,让我拿来直接用了(懒懒懒,也是没治了),不过保存一定要断开与符号的链接。树的变大速度依旧用了线性,时间定义为12s。
房子和沿设定轨迹运动的太阳可以放到同一个SVG里(最好在两个图层,防止代码看上去太乱),关于沿轨迹运动,这是另外一个教程,涉及到方向和根据轨迹起点位置对运动元素的位置校正,后面会单独放一个全新的教程里。整个动画的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>叠加动画</title>
<style type="text/css">
@keyframes changeScale{
0% {width:50px;height:50px; top:270px; left:145px;}
100% {width:300px;height:300px;top:20px; left:20px}
}
#tree{position:absolute;animation:changeScale 12s linear 0s infinite; }
#sun{position:absolute;left:20px;top:20px;width:500px;height:300px;}
</style>
</head>
<body>
/*以下为树SVG*/
<svg id="tree" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" >
此处夹杂一大堆树的代码……
</svg>
/*以下为太阳和房子SVG*/
<svg id="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 300" >
<g>
此处夹杂一大堆太阳的代码……
<animateMotion path="M467.3,271.3c0,0-3.8-230.3-208.6-229.1C32.8,43.4,26,267.6,26,267.6" dur="2s" repeatCount="indefinite" rotate="auto" calcMode="spline" keySplines="0.42 0 1 1"
keyTimes="0;1" /> /*路径运动动画*/
</g>
<g>
此处夹杂一大堆房子的代码……
</g>
</svg>
</body>
</html>
那一堆图形的代码实在太多,而且看了也没什么意义,就不放了,这样完成整个动画之后我们的文件大小在40K,要远远小于视频格式或者动图格式(轻则几兆)。而且配合JavaScript可以很好的完成一些交互。
呼,教程到此结束,录屏真的录到手软……
在没有开始学习CSS3动画时,一直都是用SVG的动画属性来完成效果,而现在再把这些全部知识贯通起来之后,思路就清晰了很多,SVG用来绘制图形和路径动画,CSS3来完成变形动画效果,JavaScript来控制动画节点以及获取参数和赋值。