以下是 Dennis Gaebel 的客座文章。 Dennis 在 CodePen 上创建了一些非常迷人的多边形 SVG 效果,在这里他将分享他是如何做到的。
有时,您最意想不到的事情会获得最多的关注,就像我在 CodePen 上发布的 Polylion 一样。 我认为动画效果的简单性很容易理解,因为我在代码方面没有做任何疯狂的事情,但我猜最终结果很酷。 我想与大家分享这个动画是如何以及为什么实现的。

如果您没有关注我的 Twitter,那么让我告诉您。 我正在为 Tuts+ 撰写一个关于 TimelineMax 文章系列,重点介绍 GreenSock 的 TimelineMax。 从本质上讲,它从初学者到高级,并为读者提供工作示例,让他们自己进行测试。 对多边形动画的研究也始于我为 Jonno Riekwel 在 Polyon 完成的一个项目的练习,所以这对每个人来说都是双赢的。
The Polyman
我开始我的研究,检查了 我在 CodePen 上找到的 Polyman SVG。 最初它是用 CSS 完成的(悬停时也会爆炸 \o/),但我想研究一下对每个多边形形状进行更精细控制的能力。 使用 TimelineMax 同时显示多边形的结果如下所示。

由于 SVG 在 <g>
标签内包含了人的一部分(耳朵、脸等),因此使用 JavaScript 连接到每个部分变得非常容易。 由于 SVG 是 XML,因此创建它的所有内容都只是一个节点。 在 jQuery 中,选择器是这样的:$('svg g#shirt path')
。
Polylion 设置
对于狮子,我想单独获取每个多边形元素 $('svg.polylion > polygon')
以获得最大控制权,并像您看到的那样为每个元素提供级联效果。 显然,结果超级棒,坦率地说,制作起来也不错。 让我解释一下狮子是如何获得它的灵感的。
由于我经常在 CodePen 上闲逛,我偶然看到了 Dmytro Batarin 发布的狮子作品 SVG 低多边形狮子,它似乎是 最初由 Breno Bitencourt 在 Dribbble 上发布的,他还撰写了关于制作多边形矢量作品的文章 这里。 如果您没有时间阅读 Breno 撰写的文章; 整个 SVG 是手工制作的。 它背后没有任何障眼法,显然这是目前获得最佳结果的唯一方法。

由于设计部分已经为我完成了,所以我真正需要做的就是集成 TimelineMax 并调整我的配置,以便实现我想要的效果。
Polylion 代码
查看 Dennis Gaebel (@grayghostvisuals) 在 CodePen 上的 Pen SVG 低多边形狮子:动画多边形。
在我们进入真正有趣的部分之前,让我们看一下 SVG 的 XML 输出。
<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 没有太多内容。 除了我们知道它很难制作之外,输出非常简单。 如果您不熟悉 polygon 元素,可以 在这里 阅读更多相关信息。 polygon 元素定义了一个封闭的形状,该形状由一组连接的直线段组成。
JavaScript 是唯一能够计算多边形数量的方法,以避免使用手指和脚趾。 正如我之前提到的,GreenSock 的 TimelineMax 用于控制每个多边形形状。
我从 TimelineMax 的初始设置开始,包括一些变量,例如配置 (tmax_options
) 和时间轴构造函数 (TimelineMax()
)。
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,以便 polylion 序列反向动画。
设置
对于我设置的其余部分,我定义了一些变量,以便稍后在我的代码中引用。
var svg_length = $('svg.polylion > polygon').length,
svg_shapes = [],
stagger_val = 0.00475,
duration = 1.5;
动态计算多边形数量的唯一方法是使用 JavaScript,这正是我们正在使用的(我们查询所有多边形,然后计算它返回的集合的长度)。 svg_shapes
变量只是一个空数组,我稍后会详细解释。 其余部分用于更简单的配置,定义整个动画持续时间(以秒为单位)以及我希望每个多边形在回放期间交错的量。
由于 TimelineMax 的第一个参数可以是元素数组,因此我在循环中计算每个元素并将结果推送到我们之前创建的空数组中。 另请注意,我们正在使用 :nth-of-type
CSS 选择器单独获取每个多边形。
for (var i = 1, l = svg_length; i <= l; i++) {
svg_shapes.push($('svg.polylion > polygon:nth-of-type('+ i +')'));
}
其余配置是标准设置内容,但这是魔法发生的地方。 我们的第一个对象文字包含我们希望对象从中进行动画的对象的 CSS 属性和值,第二个对象文字是我们正在对其进行动画的属性。 使整个内容脱颖而出的真正原因是弹性缓动,它使作品具有微妙的反弹效果。
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 构造函数引用,以便赋予狮子生命力。
tmax_tl.staggerFromTo(svg_shapes, duration, stagger_opts_from, stagger_opts_to, stagger_val, 0);
只有一行代码就赋予了这幅作品生命。 结果是神奇的!
是的,但这是“CSS-Tricks”,而不是“JS-Tricks”
我明白了。 我们仍然可能会使用 JavaScript 来计算多边形,但是一旦我们知道了这一点,我们就可以使用像 Sass、LESS 或 Stylus 这样的预处理器来创建循环以完成工作。 让我们尝试使用 Sass 的功能以及 Jord Riekwel (@Larkef) 为我之前提到的 Polyon 项目创建的这只狮子。
以下是用 CSS 实现上述 Polyman TimelineMax 动画的示例。

@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;
}
以下是用相同方法实现的另一个很酷的效果,但对多边形使用了不同的转换(轻微的缩放和旋转)。

在经过一些修改后,以下是我们最终得到的结果。
查看 Dennis Gaebel (@grayghostvisuals) 在 CodePen 上的 Pen Polyon SVG 狮子。
为了在 Sass 中获取循环的数字,我使用 JavaScript 统计了存在的 polygon 元素的长度。 我还手工将鬃毛与脸部分开,以便我们可以独立控制这些部分。 我将与脸部和鬃毛相关的每个 polygon 元素分组到一个 <g>
标签中。 您可以在上面笔的 HTML 输出中看到这一点。 正如我所说,为了统计 polygon 元素的长度,我使用了 JavaScript,如下所示……
var polygon_mane = $('svg > g#polyonlion-face polygon').length;
console.log(polygon_mane);
现在我有了脸部的数量,我可以对鬃毛做同样的事情。 我得到的结果值为 26 和 76,使总的多边形数量为 102(76 + 26 = 102)。
$polyonlion-count: $polyonlion-count-mane + $polyonlion-count-face; // reports 102
$polyonlion-count-mane: 26;
$polyonlion-count-face: 76;
如上所述,我们将计数值定义为变量以供参考。 下一步是为 SVG 本身定义一些属性,并设置动画 @keyframes
调用。
@keyframes polyonlion-animation {
to {
transform: scale(1);
opacity: 1;
}
}
svg.polyonlion {
width: 98px;
height: 115px;
}
设置了一些宽度和高度等内容,我们还配置了一个动画,该动画声明“从声明中当前设置的属性转到此处指示的属性值”。
下一步是最初完全从视图中移除对象(即使其不可见)。 代码中使用的缩放转换和不透明度值用于缩小和隐藏多边形,以使狮子不可见。 我们还表示希望当它们转换时,原点位于多边形本身的中心。 从本质上讲,这可以分解为对象从自身中心向外进行动画。
.polyonlion {
width: 98px;
height: 115px;
> g polygon {
transform: scale(0);
transform-origin: center center;
opacity: 0;
}
}
为了对上面的代码块进行最终润色,我将添加几行代码以防 JS 被关闭或动画属性不受支持。 对于此任务,我正在使用 Modernizr 及其放置在 HTML 标签上的功能类。
.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)。我们还需要在每次循环迭代中将动画延迟乘以多边形的数量,从而为动画带来一些随机性。
@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 加载,然后运行一个 900 毫秒的setTimeout
,最后在 body 上放置一个触发我的动画序列的类。所有这些在 jQuery 中看起来像这样
$(document).ready(function() {
setTimeout(function() {
$('body').addClass('polyonloaded');
}, 900);
});
结束语
我再怎么强调 SVG 现在有多酷都不为过,但我相信你已经知道了。这真是太疯狂了,因为社区或像 CodePen 这样的地方对 SVG 在动画方面的能力进行了深入的研究,标准越来越高。当你有一些空闲时间时,一定要查看我在 CodePen 上的收藏,我在那里收集了我最喜欢的 SVG 动画。你也可以随时查看CodePen上的开发者,他们每天都在用 SVG 创建令人惊叹的动画。
其他参考
这里有一些关于在 Photoshop 中创建多边形艺术的 YouTube 视频
很棒的文章!喜欢你的作品,Dennis!
谢谢 Evan。继续创造很棒的东西 :)
很棒的帖子!只是提醒一下,这句话“正如我之前提到的,GreenSock 的 TimelineMax 用于控制每个多边形形状,坦率地说”被截断了——只是想知道你接下来要说什么。
我也喜欢使用 GSAP 和 SVG——时间轴和交错变得非常强大,你在文章中很好地展示了这一点。干得好!
谢谢 Sarah。是的……用几行 GSAP 可以做到的事情真是太神奇了 \o/
太棒了!感谢分享,Dennis!
没问题,Tony \m/
在你的原始 Codepen 示例中,遍历 jQuery 数组是不必要的。你可以将原生 jQuery 对象提供给 TimelineMax 并节省一些工作。
下面是一个简化的示例。
http://codepen.io/colin/pen/EaEJpL
嘿,Colin。观察入微。是的,你这么说很有趣,因为我今天早上正在给自己倒咖啡,并想到了同样的事情。我没有为 Polyman 做这件事,所以我不确定为什么在这里这样做?无论如何……再次感谢。很棒的发现!
太酷了——我理解所有代码部分,这一切都有意义……我只是需要学习如何做艺术部分……这就是生活。
附言:我真的很讨厌这样做,但文章中有很多“it’s”。“It’s”总是“It is”,而不是所有格“its”。
厉害!这就是我原本想让你在 CodePen 芝加哥聚会上发表的演讲……;
哈哈!实际上我还有很多东西要补充到这个(开发和艺术作品本身的创作)。我正在完成 Polyon 项目的一些最后润色,此外 GreenSock 的 Jack 还给了我一些值得讨论的改进建议。关于这些演示的性能和动画,还有很多话要说 \o/
这太不可思议了。太棒了,感谢提供的链接!我希望这在现代网页设计中能更频繁地被采用 :)
我想我需要做更多 :) 感谢你的好意 \m/ 链接的视频即使只是观看也很有趣。享受!
太酷了!我的一位朋友实际上有这种绘画风格。是时候深入了解这个 Timeline Max 的东西并扫描他的一些画作了!感谢这篇文章/教程!
没问题……嗯……Dennis ;)
太棒了。继续努力。
没问题,Arun!给你!http://codepen.io/grayghostvisuals/full/radeqX
你用这篇文章彻底激励了我!我昨晚画了一张自己的低多边形肖像,用来配合这个效果。
http://codepen.io/anon/pen/gbzMjj
糟糕,这是 CodePen
http://codepen.io/daelen/pen/WbJxaB
哇!太棒了!你激励我开始了一个多边形动画合集。你应该看看……可能会认出其中一个 ;)
太棒了!
太棒了!我真的很喜欢它,感谢分享
哇!当我看到我的名字出现在 css-tricks 上时,你能想象我的惊讶吗?:D
很棒的文章,哥们 :)
我发现使用一些德劳内三角剖分工具可以帮助更容易地生成图像的多边形版本。它们不会生成 SVG,但可以用来更容易地创建 SVG 版本。
或者有人可以修改这些工具以生成 SVG 输出,那将非常棒!
太棒了。
感谢分享。
http://www.vacib.info/
感谢这篇文章——我喜欢它!
查看 Github 上的这个项目
https://github.com/snorpey/triangulation
谢谢 Thomas。我以前从未见过那个项目……太酷了!感谢分享 :)