有时候,你最意想不到的东西,却能获得最多的关注,正如我发表在CodePen上的多边形狮子的样例。我没有做任何超级棒的代码效果,因为我认为简单的动画效果是很容易理解的,但是最后的结果却是很棒的。在这里,我想要和你们所有人分享这个动画如何以及为什么做出来的。
如果你没有关注我的Twitter,那我来给你们讲解一下吧。我正在Tuts+上写一系列的关于使用GreenSock中的TimelineMax的文章,基本上它为从初级到高级的读者都提供运行示例,供读者进行自我测试。多边形动画的研究也开始于我为Jonno Riekwel做的一个多边形项目实践,所以基本上这是双赢的。
Polyman
我开始我的研究是因为在CodePen上找到的一个Polyman SVG。它最初是使用CSS完成的(在鼠标移上去的时候也会有爆炸的效果(^o^)/~),但是我想探讨出能更好地控制每个多边形的方法。结果就是下边你看到的使用TimelineMax完成的多边形效果。
由于SVG的 <g>
标签内包含了头像的各个部分(耳朵、脸等等),这使得它能够很方便地与JavaScript一一衔接。由于SVG是XML格式的文档,所以创建SVG其实就是创建一个结点。在jQuery中,它的选择器是这样写的 $('svg g#shirt path')
。
Polylion设置
在Polylion中,我想单独抓取对每个多边形元素的最大控制,并给每一个元素一个级联效应。显然,结果看起来是非常混乱的,但是坦白说,这做起来并不难。让我讲解给你们一下这只狮子是如何得到它的魔力的~
因为我经常在CodePen上转悠,某天我正好瞥见了Dmytro Batarin在Pen上发表的低多边形狮子SVG图像,这最初是由Breno Bitencourt发表在Dribbble上的。Breno Bitencourt还写了制作多边形矢量图的过程,点击这里阅读。这整个SVG是纯手工制作的,完全没有使用特效和滤镜等,而且很明显这是当时能得到这个成果的唯一方法。
使用以前的纯手工…方法制作的多边形SVG图像
由于设计的部分已经都做好了,所以我需要做的就是结合TimelineMax,调整一些设置来达到我完成后的效果。
Polylion代码
在我们获得有趣的效果前,先看看我们SVG的XML输出。
SVG
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600" class="polylion"> <polygon points="392,85 380,128 339,98" style="fill: #FADFAA" /> <polygon points="392,85 380,128 412,111" style="fill: #EABA8C" /> <polygon points="339,98 380,128 340,140" style="fill: #FAD398" /> <polygon points="339,98 340,140 309,142" style="fill: #DFA387" /> <polygon points="339,98 309,142 286,133" style="fill: #F9D8AD" /> <polygon points="392,85 412,111 443,101" style="fill: #DBB08E" /> <polygon points="443,101 412,111 434,126" style="fill: #D59F7D" /> <polygon points="443,101 434,126 475,122" style="fill: #FACC91" /> <polygon points="412,111 380,128 402,132" style="fill: #CE8670" /> <!-- and so on --> </svg>
这个SVG并不长。事实上我们知道这是很难完成的,但是输出相当简明。如果你对多边形元素不熟悉,你可以先看看这个。多边形元素是由一组相互连接的直线线段组成的封闭形状。
JavaScript是避免手脚并用来对多边形进行计数的唯一方法。正如我前面提到的,GreenSock中的 TimelineMax可以用来控制各个多边形。
我从TimelineMax的初始设置开始,涉及几个变量的设置,如配置(tmax_options
)和时间轴构造器(TimelineMax()
)。
JavaScript
var tmax_options = { delay: 0.25, // init pause time repeat: -1, // make it repeat repeatDelay: 0.25, // delay this amount on repeat yoyo: true // also play sequence in reverse }; var tmax_tl = new TimelineMax(tmax_options);
基础配置表现为一个对象文本,狮子动画序列相对初始播放状态延迟了0.25
秒,设置动画重复,延迟回播序列0.25
秒,最后设置 yoyo
值为true
,以便多边形狮子的序列动画反序播放。
配置
对于配置剩余的步骤,我在后边的代码里定义了几个变量作为参考。
jQuery
var svg_length = $('svg.polylion > polygon').length, svg_shapes = [], stagger_val = 0.00475, duration = 1.5;
动态计算多边形的数量的唯一方法是使用JavaScript,这也正是我们在使用的(我们把他们全部遍历一遍,然后计算并返回集合的长度), svg_shapes
变量只是一个空的数组,我会过后再详细讲解。剩下的是简单的设置,定义整个动画的长度(秒),以及在播放过程中各个多边形交互的数量。
因为TimelineMax的第一个参数可以是一个元素数组,所以我使用一个循环来计算,然后把结果放到我们之前创建的一个空数组内。还要注意的是,我们正在使用:nth-of-type 这个CSS选择器抓取每一个单独的多边形。
JavaScript
for (var i = 1, l = svg_length; i <= l; i++) { svg_shapes.push($('svg.polylion > polygon:nth-of-type('+ i +')')); }
其余的设置都是按照标准设置来的,但是这正是狮子魔力展现的地方!我们的第一个对象文本包含了我们想要对象开始动起来的CSS属性和值,第二个对象文本包含的属性是我们动画要运行的效果。真正使得这个效果发生的是弹性缓解的属性,它给予了图形微妙的反弹。
JavaScript
var stagger_opts_from = { css: { scale: 0, transformOrigin: 'center center', opacity: 0 }, ease: Elastic.easeInOut, force3D: true }; var stagger_opts_to = { css: { scale: 1, opacity: 1, }, ease: Elastic.easeInOut, force3D: true };
现在我们可以把TimelineMax的 staggerFromTo
方法关联到TimeLineMax的构造器上,让狮子可以动起来!
JavaScript
tmax_tl.staggerFromTo(svg_shapes, duration, stagger_opts_from, stagger_opts_to, stagger_val, 0);
仅一行的代码,就给了这件艺术品生命,这是多么神奇!
Yeah, but this is “CSS-Tricks” not “JS-Tricks”
我也知道。我们可能仍然使用JavaScript来计算多边形的数量,但现在我们知道了,可以使用一个预处理器(如Sass,lLESS或者Stylus)来完成。我们尝试使用了Sass,这只狮子是由Jord Riekwel (@Larkef)为我前面提到的多边形项目创建的。
这里的多边形头像TimelineMax动画只使用了CSS来制作效果。
CSS
@keyframes polyonlion-animation { to { transform: scale(1); opacity: 1; } } svg.polyonlion > g polygon { animation: polyonlion-animation 400ms linear 1 forwards; transform: scale(0); transform-origin: center center; opacity: 0; }
这是另一个使用同样方法创建出的很棒的效果,但是使用的是不同的多边形转换效果(轻微的缩放和旋转)。
经过了一些修改后,这是我们最后完成的效果。
为了获得在Sass中循环的数目,我使用了JavaScript来计算存在的多边形的长度。我也是手工分离鬃毛和脸部的,这样我们可以单独控制这些部分。我把有关脸部的各个多边形元素以及鬃毛取出,在一个 <g>
标签中组合。你可以在上面的PEN代码中查看html输出的结果。就像我说的,为了计算多边形的长度,我使用了如下的JavaScript代码:
jQuery
var polygon_mane = $('svg > g#polyonlion-face polygon').length; console.log(polygon_mane);
既然我已经对脸部做了计算,现在我可以对鬃毛做同样的计算。我分别计算出的值是26
和76
,因此多边形的总数量是102
(76 + 26 = 102
)。
SASS
$polyonlion-count: $polyonlion-count-mane + $polyonlion-count-face; // reports 102 $polyonlion-count-mane: 26; $polyonlion-count-face: 76;
如上所述,我们定义了计数值作为基准变量。下一步是定义几个SVG本身的属性,然后设置动画的 @keyframes
调用。
CSS
@keyframes polyonlion-animation { to { transform: scale(1); opacity: 1; } } svg.polyonlion { width: 98px; height: 115px; }
一些像height
和width
的值已经设置好,我们也设置了动画的状态为“从当前声明中设置的属性,到这些属性值显示在这里”。
下一步是从初始的视图中完全删除这些对象(即让它们不可见),代码中的尺寸变换和透明度的值是指,接下来缩小和隐藏多边形,使得狮子不可见。我们也提到了我们要让起点在他们转换时成为多边形的中心点,即从中心向外爆裂的对象动画。
SCSS
.polyonlion { width: 98px; height: 115px; > g polygon { transform: scale(0); transform-origin: center center; opacity: 0; } }
最后再做一些完善,我多加了几行代码作为备用,在js关闭或者不支持动画属性的情况下可以运行。这块东西我是使用了Modernizr和它放在HTML标签中的特色类。
SCSS
.polyonlion { width: 98px; height: 115px; > g polygon { transform: scale(0); transform-origin: center center; opacity: 0; .no-js &, .no-cssanimations & { transform: scale(1); opacity: 1; } } }
现在我们需要稍微延迟狮子脸上(包括鬃毛)的多边形动画。为了完成这两个东西,我们需要在(76
,26
)之间加两个循环,还需要在每个循环中用多边形的数量乘以动画的延迟时间,让动画有一些随机性。
SCSS
@for $i from 1 through $polyonlion-count-face { .polyonloaded .polyonlion > g#polyonlion-face polygon:nth-of-type(#{$i}) { animation: polyonlion-animation 100ms linear 1 forwards; animation-delay: 0.0275s * $i; // 0.0275s * 1, 0.0275s * 2, etc. } } @for $i from 1 through $polyonlion-count-mane { .polyonloaded .polyonlion > g#polyonlion-mane polygon:nth-of-type(#{$i}) { animation: polyonlion-animation 100ms linear 1 forwards; animation-delay: 0.0475s * $i; // 0.0475s * 1, 0.0475s * 2, etc. } }
你可能注意到我使用了一个叫 polyonloaded
的类,这个类的作用是在DOM加载时,控制动画的加载和执行。基本上,我等到DOM加载完成,然后执行一个0.9
秒的 setTimeout
方法,最后给body
加上一个类函数,用于触发我的动画序列。这一个过程在jQuery中是这样写的:
jQuery
$(document).ready(function() { setTimeout(function() { $('body').addClass('polyonloaded'); }, 900); });
总结思考
我没有强调SVG是多么的酷炫,但是我敢肯定你已经知道SVG真的很棒。在一些社区或像CodePen的地方已经很有力地检验出SVG有多么棒。如果你有空闲的话,一定要看一下我在CodePen上的收藏,这都是我之前收集的我最喜欢的SVG动画。你可以经常在CodePen上找到一些创建了很棒的SVG效果的开发者。
参考资料
这是一些在Photoshop中创建多边形作品的YouTube教学视频:
-
Tutorial-photoshop polygon
-
Low Poly Portrait Tutorial
-
Low Poly Vector Tutorial