UI设计师福利之零代码基础SVG缩放动画教程

首先把基础效果放上,一个动态缩放的圆形。

circle.gif

这是一个模板,里面的代码可以直接复用,并可以延伸出一系列效果,主要是为了方便UI设计师只需要通过AI生成的SVG文件直接进行内容替换,让不会CSS3动画属性的UI也能轻松的实现类似的动画效果。
以后会陆续更新针对UI设计师的这种SVG动画教程,宗旨在于打破代码壁垒,让UI设计师专注于创意与设计。我会把代码尽量标准化,只需要“拷贝-粘贴”就能实现一些不错的动画效果。
先来说一下如何实现,如果学过一点点的SVG的小伙伴们,基础图形的绘制并非难事,直接可以码出circle以及cx,cy,r,fill等参数值,但对于零代码基础的UI来说,我们需要的只是在AI中建一个画布,画一个圆。

AI绘制一个圆形.png

看过我的其他文章的小伙伴们应该知道,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值的设定留出了边距。

第一个关键帧(初始)示意图.png
第二个关键帧示意图.png
第三个关键帧(终止)示意图.png

而我们之所以经过精确计算,目的则是为了让SVG(并非里面的圆形)的中心点可以重合,最终实现完美的缩放效果。

SVG缩放原理.png

中间添加的关键帧可以有很多,比如你可以按顺序写10%,25%,60%……随便定义。也可以没有,则平滑的缩放,没有停顿效果。

删除50%关键帧之后的效果.gif

简单解释一下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.缩放同时颜色改变###

先看下面这种效果,星星缩放的同时伴随透明度的改变

s.gif

在模板基础上需要修改的有两个部分,一个是用星星替换圆形,一个是增加一个改变透明度的动画。还是在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}
}

然后就得到了下面这种效果:

缩放伴随颜色变化.gif

2.缩放同时旋转###

继续用AI自带的螺旋线形状,生成<path>。这里我改了一下,为了让旋转看起来更顺畅,我去掉了50%关键帧,把运动速率由ease(慢-快-慢)改成了线性linear,并且去掉了旋转效果的逆向播放(删除alternate),始终保持同一个方向的旋转,得到下面的效果。

缩放伴随旋转.gif

对应代码如下:

<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.不同效果叠加###

有了上面的基础,可以放个大招了,来实现一个多种动画叠加的效果,如下图(不要说丑,也做了很久呢):

复合动画.gif

动画其实可以拆成三部分,一部分是慢慢变大的树,我把它用我们的缩放模板来完成,不过个别参数修改了一下;一部分是沿着轨迹运动的太阳(太阳直接借用的素材,轨迹路径是自己建的);一部分是静止的小房子(直接借用的素材)。
因为不止用了一个SVG,所以我把这些放进一个html文件。先从位置示意图分析一下各种参数的设置。

复合动画拆解.png

先来说树,与我们前面的辐射形状缩放的动画不同,我们需要它从水平线变大,缩放的中心点已经在上图中标注了。尺寸我希望从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来控制动画节点以及获取参数和赋值。

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

推荐阅读更多精彩内容