使用 CSS 动画 SVG

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费赠送额度!

动画 SVG 的方法不止一种。<animate> 标签可以直接放到 SVG 代码中。还有一些库可以帮助您,例如 Snap.svgSVG.js。我们将探讨另一种方法:使用内联 SVG(直接在 HTML 中的 SVG 代码)并通过 CSS 动画各个部分。

我最近个人玩过这个,因为我的母校 Wufoo 希望更新我们在这里播放的广告图形。我最近在这里的设计大量使用了 SVG,我认为这将是另一个绝佳的机会来更多地使用它。

最终产品非常简单。它就是这个样子

查看 CodePen 中 Chris Coyier 的 Wufoo SVG 广告 (@chriscoyier) on CodePen.

让我们看看它是如何完成的。

1. 设计广告/有计划

这可能看起来像一个 如何画一只猫头鹰 的时刻,但这篇文章是关于动画的,所以让我们尽快进入正题。

我为这个广告制定的计划是制作一个超级简单的 Wufoo 广告,使用他们经典的徽标、颜色和总体品牌。然后添加一些风格。

  1. 让字母稍微跳出页面。Wufoo 是一个有趣的词,让字母也玩得开心。
  2. 过去我们制作过一件 T 恤,正面有恐龙,背面写着“快速、智能、强大”。这些都是恐龙和 Wufoo 的特点,更不用说 FORMidble 这个有趣的文字游戏了。让我们让它们淡入淡出。
  3. 为了与恐龙完全联系起来,我们将让一只霸王龙从底部探出头来,好奇地张望,然后迅速离开。“快速。”这个词将在它离开时出现,这是一个很好的联系。

我在 Illustrator 中将所有部分组合在一起。

请注意徽标和标语文本是如何轮廓显示的。这意味着它们只是矢量形状,并且将在 SVG 中完美渲染为 <path>。您在那里看到的文本“快速。”在 Illustrator 中保留为文本。

当我从 Illustrator 中保存它时,它将被保留为 <text> 元素。

2. 另存为 SVG

Illustrator 可以直接将它另存为 SVG

您可以在代码编辑器中打开该 SVG 文件并查看 SVG 代码

3. 清理 SVG,为形状添加类名

您可能想运行它通过 SVGO 来优化它并删除 DOCTYPE 等。但更重要的是,对于这篇文章,您需要为不同的形状添加类名,这样我们就可以在 CSS 中选择它们并做一些事情!

<svg version="1.1" id="wufoo-ad" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" enable-background="new 0 0 400 400" xml:space="preserve">

  <!-- background -->
  <rect class="wufoo-background" fill="#D03E27" width="400" height="400" />

  <!-- logo letters -->
  <path class="wufoo-letter" fill="#F4F4F4" d="M60.858,129...." />
  <path class="wufoo-letter" fill="#F4F4F4" d="..." />
     <!-- etc -->

  <!-- dinosaur -->
  <g class="trex">
     <path ... />
     <path ... />
  </g>

</svg>

4. 插入 SVG

您可以将该 SVG 代码直接复制粘贴到您想要放置广告的 HTML 中。但这可能会弄乱模板。很有可能您只需要做一些类似的事情

<aside class="sidebar">
  
   <div class="module module-ad">
      
       <?php include("ads/wufoo.svg"); ?>

   </div>

   ...

5. 动画!

现在我们在 DOM 中有了这些形状,我们可以像任何其他 HTML 元素一样定位和设置它们,让我们来做吧。

假设我们要将它作为一个 10 秒的时间轴

文字先淡入淡出

我们希望第一件事发生是“快速、智能、强大”。每个词将显示一秒钟。因此,我们将创建一个动画,让该词显示 10% 的时间

@keyframes hideshow {
  0% { opacity: 1; }
  10% { opacity: 1; }
  15% { opacity: 0; }
  100% { opacity: 0; }
} 

然后定位第一个词,让动画持续 10 秒(10% 是 1 秒)

.text-1 {
  animation: hideshow 10s ease infinite;
}

接下来的两个字母将从隐藏状态开始(opacity: 0;),然后使用完全相同的动画,只是延迟一点开始

.text-2 {
  opacity: 0;
  animation: hideshow 10s 1.5s ease infinite;
}
.text-3 {
  opacity: 0;
  animation: hideshow 10s 3s ease infinite;
}

每个字母上的额外 0.5 秒是为了适应前一个词的淡出时间段。

字母弹出

一旦这些字母完成动画,我们将让 WUFOO 中的字母执行它们的摇摆跳跃,就像这样

这里的技巧是我们让动画只持续 5 秒,但向前运行一次,向后运行一次。这样,它就与我们 10 秒的时间轴相匹配,位于我们想要的位置,并且我们只需要在一个方向上缩放,因为当它反转时,它会缩回到原位。

每个字母都有轻微的延迟,因此它们会稍微偏离中心

.wufoo-letter {
  animation: kaboom 5s ease alternate infinite;
  &:nth-child(2) {
    animation-delay: 0.1s;
  }
  &:nth-child(3) {
    animation-delay: 0.2s;
  }
  &:nth-child(4) {
    animation-delay: 0.3s;
  }
  &:nth-child(5) {
    animation-delay: 0.4s;
  }
}
@keyframes kaboom {
  90% {
    transform: scale(1.0);
  }
  100% {
    transform: scale(1.1);
  }
}

以上只是为了简洁而使用 SCSS,不包括任何前缀(正如您在生产中需要的那样)。

我觉得 animation-delay 是一个属性,它将受益于 CSS 中的本机随机化。如果看到字母每次随机延迟一点会很不错。

恐龙最后

一旦文字完成,恐龙就会露出头来。即使恐龙是由许多 <path> 组成,我们也可以通过定位包裹它们的 <g>(组)标签来定位它们。

因为使用 translate 来动画位置 更好,我们将在关键帧中这样做

@keyframes popup {
  0% {
    transform: translateY(150px);
  }
  34% {
    transform: translateY(20px);
  }
  37% {
    transform: translateY(150px);
  }
  100% {
    transform: translateY(150px);
  }
}

我们希望这个动画“持续”大约 3 秒。它实际上以 10 秒的循环运行,但您只会看到它在 3 秒内执行操作。当 translateY(150px) 生效时,恐龙会被移动到太低的位置,您什么也看不见。在动画的 37%(大约 3 秒)时,您会看到它缓慢地向上移动,然后快速向下移动。

当我们应用这个动画时,我们将确保

恐龙一开始是隐藏的
动画延迟,以便在文字完成淡入淡出舞蹈后立即开始。

.trex {
  transform: translateY(150px);
  animation: popup 10s 6.5s ease infinite;
}

恐龙在最后一秒弹出,此时“快速。”这个词会重新出现在屏幕上(因为所有动画都设置为 infinite,这意味着它们会无限期地重新运行)。这是一个有趣的协同作用。

6. 使其成为响应式/可点击的广告

SVG 的一个优点是它可以按比例缩放至任何尺寸而不会损失质量。为了使像这样的内联 SVG 在保持纵横比的同时进行缩放,我们可以使用老式的填充盒技术。

<div class="wufoo-ad-wrap">
  <svg class="wufoo-ad">
     ...
  </svg>
</div>
.wufoo-ad-wrap {
  height: 0;
  padding-top: 100%;
  position: relative;
}
.wufoo-ad {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

这里的想法是“包装”始终是一个完美的正方形,相对于其宽度。然后,我们将 SVG 绝对定位在该完美的正方形内,它会很乐意地调整自身大小。

由于这是一个广告(当然应该可以点击),而不是使用 <div> 作为包装,您可以使用 <a href="">,只需确保将其设置为 display: block;


最终结果,供参考。

我认为这种方法在展示广告方面有未来,特别是因为它拥有 CSS 控制和易于进行锐利的调整大小。