Polylion

Avatar of Dennis Gaebel
Dennis Gaebel

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

以下是 Dennis Gaebel 的客座文章。 Dennis 在 CodePen 上创建了一些非常迷人的多边形 SVG 效果,在这里他将分享他是如何做到的。

有时,您最意想不到的事情会获得最多的关注,就像我在 CodePen 上发布的 Polylion 一样。 我认为动画效果的简单性很容易理解,因为我在代码方面没有做任何疯狂的事情,但我猜最终结果很酷。 我想与大家分享这个动画是如何以及为什么实现的。

Polylion 效果

如果您没有关注我的 Twitter,那么让我告诉您。 我正在为 Tuts+ 撰写一个关于 TimelineMax 文章系列,重点介绍 GreenSock 的 TimelineMax。 从本质上讲,它从初学者到高级,并为读者提供工作示例,让他们自己进行测试。 对多边形动画的研究也始于我为 Jonno RiekwelPolyon 完成的一个项目的练习,所以这对每个人来说都是双赢的。

The Polyman

我开始我的研究,检查了 我在 CodePen 上找到的 Polyman SVG。 最初它是用 CSS 完成的(悬停时也会爆炸 \o/),但我想研究一下对每个多边形形状进行更精细控制的能力。 使用 TimelineMax 同时显示多边形的结果如下所示。

使用 TimelineMax 的 Polyman SVG

由于 SVG 在 <g> 标签内包含了人的一部分(耳朵、脸等),因此使用 JavaScript 连接到每个部分变得非常容易。 由于 SVG 是 XML,因此创建它的所有内容都只是一个节点。 在 jQuery 中,选择器是这样的:$('svg g#shirt path')

Polylion 设置

对于狮子,我想单独获取每个多边形元素 $('svg.polylion > polygon') 以获得最大控制权,并像您看到的那样为每个元素提供级联效果。 显然,结果超级棒,坦率地说,制作起来也不错。 让我解释一下狮子是如何获得它的灵感的。

由于我经常在 CodePen 上闲逛,我偶然看到了 Dmytro Batarin 发布的狮子作品 SVG 低多边形狮子,它似乎是 最初由 Breno Bitencourt 在 Dribbble 上发布的,他还撰写了关于制作多边形矢量作品的文章 这里。 如果您没有时间阅读 Breno 撰写的文章; 整个 SVG 是手工制作的。 它背后没有任何障眼法,显然这是目前获得最佳结果的唯一方法。

以传统的方式制作多边形 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 视频