动画 SVG 的方法不止一种。<animate>
标签可以直接放到 SVG 代码中。还有一些库可以帮助您,例如 Snap.svg 或 SVG.js。我们将探讨另一种方法:使用内联 SVG(直接在 HTML 中的 SVG 代码)并通过 CSS 动画各个部分。
我最近个人玩过这个,因为我的母校 Wufoo 希望更新我们在这里播放的广告图形。我最近在这里的设计大量使用了 SVG,我认为这将是另一个绝佳的机会来更多地使用它。
最终产品非常简单。它就是这个样子
查看 CodePen 中 Chris Coyier 的 Wufoo SVG 广告 (@chriscoyier) on CodePen.
让我们看看它是如何完成的。
1. 设计广告/有计划
这可能看起来像一个 如何画一只猫头鹰 的时刻,但这篇文章是关于动画的,所以让我们尽快进入正题。
我为这个广告制定的计划是制作一个超级简单的 Wufoo 广告,使用他们经典的徽标、颜色和总体品牌。然后添加一些风格。
- 让字母稍微跳出页面。Wufoo 是一个有趣的词,让字母也玩得开心。
- 过去我们制作过一件 T 恤,正面有恐龙,背面写着“快速、智能、强大”。这些都是恐龙和 Wufoo 的特点,更不用说 FORMidble 这个有趣的文字游戏了。让我们让它们淡入淡出。
- 为了与恐龙完全联系起来,我们将让一只霸王龙从底部探出头来,好奇地张望,然后迅速离开。“快速。”这个词将在它离开时出现,这是一个很好的联系。
我在 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 控制和易于进行锐利的调整大小。
用 CSS 动画一直是个问题,因为它基于百分比,而不是基于时间。 这是 GSAP 如此受欢迎的原因之一。 另一方面,SVG 动画 (SMIL) 做得相当不错,但在 IE 中完全不支持。 我正在编写 smil2css 来规避这个问题。 它本质上将 SMIL 转换为 CSS 动画,就像你的文章所建议的那样。
听起来很不错,但它对当前版本的 IE 无济于事 - 它们也不支持应用于 SVG 的 CSS 动画。
我还没有在 IE11 上测试,因为我没有 Win8,但在 Win7 上的 IE10 上运行良好。 目前 SVG 有很多浏览器问题。 这个,例如,仍然需要进入 Chrome 版本。
IE 供应商前缀不支持?
从没想过将
SVG
用作代码片段;我一直像对待普通的png
或jpg
一样链接到它们。 现在我明白了它有多容易,我将一直这样使用它们。很棒的小教程,Chris。 谢谢!
你也可以用
background-image
加载它们,这是我最喜欢的办法。好建议,Steven。 如果你用
background-image
加载它们,你仍然可以在你的 CSS 中定位类和 id 参数吗?Tom,我还没有测试过,但我估计,当 SVG 以样式资产的形式加载时,它无法访问其父文档的样式表。 不过,如果你将相关的 CSS 嵌入到 SVG 文件中的 <style> 中,它肯定可以工作。
好文章! 谢谢你的建议。
我上周一直在玩 SVG/CSS 动画,花了一段时间才弄清楚语法。 尽管我确实设法实现了一个流行的“线绘制”动画的变体:http://codepen.io/shshaw/pen/JDEsG
我主要的问题是如何以优雅的方式处理各个元素的
animation-delay
,但通过将动画的不同阶段(线绘制、笔划淡出、填充淡入)分开,我能够以我想要的方式使元素的动画交错进行。哇,Shaw,这太酷了。 干得好。
不幸的是,只有三个字在 Chrome 手机上动画。 恐龙和 Wufoo 没有,或者这是故意的?
干得好! 我最近一直在做很多 SVG 动画,很高兴能记住这种技术。 另一个优势:你可以使用媒体查询调整不同屏幕尺寸的动画。 据我所知,你无法仅用内联 SVG 动画做到这一点。
SVG 动画 (SMIL) 可以动画化 CSS 属性,所以你可以用百分比值进行动画。 媒体查询可能会让定位变得有点乱,但对隐藏/显示很有用。 事实上,这是有得有失的,因为 CSS 不能做 SMIL 能做的一切。 一个例子是沿着路径进行动画。
你为什么不用类来着色?
你可以删除 fill=”FFFFFF”,像这样
这是我过去几个月一直在学习的东西,但它相当复杂 :(
我用过这种 Illustrator 技术来创建 svg,它还会输出 svg 的 doctyoe。 我假设这是需要的。 我的想法正确吗?
听起来你试图优化 SVG 文件的大小。 如果是这样,你可能想走捷径,直接用 SVGO 运行它。
Illustrator(和 Inkscape)创建独立的 SVG 文件,这些文件完全符合 XML 规范,具有 doctype 和命名空间。
如果你只打算在浏览器中使用该图像(以及如果你的服务器设置为始终为 .svg 文件提供正确的 MIME 类型),你通常可以跳过 doctype。 如果你打算将代码剪切并粘贴到 html5 页面中(或通过 php 在服务器端导入它),那么你也可以跳过命名空间声明。
s/peak/peek/:P
很棒的分步方法。
对任何尝试将 CSS 动画和过渡与 SVG 一起使用的人来说,有一个警告:避免使用“元素,否则会很快变得非常 buggy!
http://codepen.io/AmeliaBR/pen/lshrp?editors=110
(该示例侧重于 CSS 过渡和鼠标事件)
http://codepen.io/AmeliaBR/pen/Dmoxz?editors=110
(特别关注动画 - 虽然不像 bug 那样多,但仍然不一致)
Ugh。 警告中的“应该是 <use>。 必须记住使用预览选项。
P.S. 漂亮的自动嵌入,Chris 和同事们!
扩展已经说过的内容,SVG 在移动浏览器上的支持似乎很糟糕。 本站点的绝大多数 SVG 在 Mobile Safari(iOS 6.1.6)上都是完全空白的方块,而 动画似乎根本不存在。
SVG,包括动画 SVG(JS 和纯 CSS)在我的 Nexus 设备(5 和 7)上运行良好。 它在 Xcode iDevice 模拟器上似乎也运行良好,当然,这并不说明什么;)。
非常好。 是否已经存在可以轻松为你生成 CSS 代码的软件? 只需选择你想要的动画,砰! 你就得到了它。 导出/保存后,所有内容都会整齐地编码 [HTML+CSS]。 :D
抱歉,这是一个愚蠢的问题,但我不太擅长设计。 是否需要 Illustrator,或者我们也可以在 Photoshop 中完成?
由于 SVG 的性质(矢量图形),你需要一个可以开箱即用地使用和编辑矢量的程序;Photoshop 不行。 不过,我相信除了 Illustrator 之外还有其他选择!
Photoshop:不行。 你可以使用 Inkscape,它是免费的开源软件。
这很棒,Chris,**再次!** 如果你的关键帧结束(100% 部分)与开始(0% 部分)处于相同的位置,你根本不需要定义结束,这是默认行为。
我在最近对 http://spigotdesign.com 的重新设计中使用了这种技术,使用了各种过渡和变换。
在大多数现代浏览器上运行良好。 在 Firefox 中,它非常难看。 很高兴看到 Wufoo 在 FF 中动画效果正确。
我在这里发布这个,因为这种技术可能会在旧的 Webkit 浏览器中造成很大混乱。 Webkit 中有一个奇怪的 bug,会影响包裹在 -标签中的元素。 非相对链接会破坏 css-animation。 我的旧 Safari(5.1.10)甚至完全拒绝显示页面,当它包含一个由 css 动画的内联 svg 并包裹在一个链接中时。 我仍在探索这个问题,但似乎一个解决方法可能是通过 javascript 添加链接。 然后 Chrome(35.0.1916.114)会执行动画,而旧的 Safari 会显示页面,只是没有动画。
你找到了解决方法吗? 如果可以,请与我们分享。
Oops,抱歉! 应该是:…<svg> 元素包裹在 <a>-标签中…
你可以在 Illustrator CC 中保存带有类和 id 的 SVG 代码。
CLASS:要为对象赋予一个命名类,请应用一个具有该名称的图形样式。
ID:要应用 ID,请将图层命名为你的 ID,并将你的对象放置在该图层上。
当你保存 SVG 文件时,转到“高级选项”,然后选择以下设置
profile:SVG1.1
CSS 属性:样式元素
小数位数:3
选中“输出更少元素”框
保持其余选项未选中
在文本编辑器中打开时,Illustrator 会添加内联样式,您可以删除这些样式,并改为使用 CSS 文档进行样式设置。
定义原子可重用无样式组件
使用“use”将它们分组到更复杂的组件中,并添加样式和变换
克隆复杂的组件/整个 SVG 以实现独立性