我相信你们中的大多数人一定见过这种小技巧,用 SVG 路径动画让它看起来像是在自行绘制。它非常酷。Jake Archibald 率先使用了这项技术,并在他的博客文章中详细介绍了它的工作原理:一个非常棒的交互式博客文章。Brian Suda 也在 24 Ways 上写过关于它的文章。Polygon 在自定义设计文章中成功地使用了它,并 写了一篇关于它的文章。Codrops 也提供了一些 很棒的示例。
我几乎没有要补充的,除了我的大脑只是突然明白了,所以我认为我会再解释一次,这样你就能像我一样理解它。
1. 你有一个 SVG 形状

2. 该形状必须有描边

3. 描边可以是虚线
我们可以从 Illustrator 中完成,但我们也可以通过编程的方式来完成。让我们使用 CSS 针对路径(假设我们在这里使用的是内联 SVG,或者通过 <object>
)并以这种方式应用虚线。
<svg ...>
<path class="path" stroke="#000000" ... >
</svg>
.path {
stroke-dasharray: 20;
}
这样会得到 20 像素长的虚线。

4. 这些虚线可以更长...
.path {
stroke-dasharray: 100;
}

5. 我们还可以“偏移”描边,这会移动这些虚线的位置
让我们看看我们如何动画化这些长描边的偏移量

这很简单,只要
.path {
stroke-dasharray: 100;
animation: dash 5s linear;
}
@keyframes dash {
to {
stroke-dashoffset: 1000;
}
}
6. 想象一下,有一条虚线很长,可以覆盖整个形状
没什么好看的,如果它根本没有虚线,它看起来就像完整的形状。你只需要让 stroke-dasharray
的值比描边的长度更长。
7. 现在偏移描边,这样它就不会覆盖整个形状,而是不会覆盖整个形状。
它看起来就像形状根本不存在。
8. 现在将描边的偏移量动画化回 0

如果使用 CSS,你希望 animation-fill-mode
的值是 forwards
,这样动画的最终状态将保持动画结束时的状态。
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
好了!
实时示例
为什么需要 JavaScript?
你看到的大多数 SVG 线性动画示例都使用了 JavaScript。这是因为很难知道描边的实际长度。在我们的示例中,我们使用了 1000
,因为这正好是合适的长度。
你可以在 JavaScript 中获取该长度,方法如下
var path = document.querySelector('.path');
var length = path.getTotalLength();
然后根据需要使用它。我在文章开头提到的那些文章更详细地介绍了所有这些内容,所以你可以参考那些文章,了解更多高级内容。我只是想介绍一下这个概念,也许你也可以理解它。
还有一个技巧!看看 一个让绘制 SVG 线变得更简单的技巧。
很棒的文章,谢谢!
不错!
我无法从非路径中获取总长度。所以我做了一个小工具,可以先将所有非路径转换为路径,然后再计算长度和动画。
我在我的婚礼网站上使用了它:http://10-5.de/
你可以在我的 CodePen 上看到代码:http://codepen.io/niorad/pen/xmfza
哇,这是一个非常酷的婚礼网站,也是 SVG 动画可以做到的一个很好的例子。
祝你们婚礼一切顺利,网站真的很好。
太棒了!
正如往常,使用属性来实现他们从未打算实现的效果 :)
太棒了。如此简单的方法可以用来产生一些很棒的效果!
非常酷,但遗憾的是,不支持 Internet Explorer。甚至 IE11 也不支持。
那么 IE 就没有 SVG 动画了。创建一个回退解决方案!
我发现获得良好的跨浏览器支持的唯一方法是使用 JavaScript 为 IE9 及更高版本进行动画。这里有一个不错的入门参考 -> 动画化 SVG
我还发现这在 IE 中不起作用。Snap.svg 是一个非常棒的替代方案。这里的所有技术和基本理论都适用;你创建一个具有给定长度的
path
,然后将strokeDasharray
和strokeDashoffset
设置为相同的长度。然后你可以执行path.animate({strokeDashoffset: 0}, 1000);
来实现相同的效果(1000 是毫秒为单位的时间)。非常棒!我做了一个使用它的实验。但为了在 Chrome 中运行,我不得不添加
@-webkit-keyframes
和-webkit-animation
。你可以在 这里看到它。
我不理解这部分。
“现在偏移这个笔触,以便它不再覆盖整个形状,而是**不**覆盖整个形状。”
如果你将虚线数组设置为与笔触长度相同,为什么偏移它会使它开始消失?剩下的部分去哪里了?
是的,这很奇怪。我想这是因为当你使用虚线的时候,总是需要至少有一条虚线和一个相同长度的间隙。所以,根据虚线或间隙在哪里对齐,笔触的哪一部分看起来是填充的。
设置
stroke-dasharray: 1000;
只是设置stroke-dasharray: 1000 1000;
的简写,即一个 1000 像素的虚线,后面跟着一个 1000 像素的间隙。来自 规范您好 Chris
我刚刚尝试运行这段代码,我在我的系统上(复制粘贴代码后)无法获得任何输出。
但更让我惊讶的是,它在 codepen 上运行得很顺利,但在 jsbin 或 jsfiddle 上却不行。
(http://jsfiddle.net/65LzR/ “fiddle”)
请分享您的看法。
使用的浏览器:chrome 32
看起来动画正在正确初始化。通过在 Chrome 中打开它并切换动画属性,它就可以正常运行。
大家好,
这是因为当前版本的 Chrome 要求 CSS 动画使用 -webkit- 前缀。
所以应该是 “-webkit- animation: 以及 @-webkit-keyframes”。
http://jsfiddle.net/SeKLe/ – 这是您演示的带添加前缀的版本。
很棒的教程,感谢分享。
太棒了!
太棒了!谢谢。您是否有任何资源/文档用于使用 CSS(或甚至 JS,例如与出色的 greensock 动画库 结合使用)进行动画处理的 SVG 属性?
这比我目前正在使用的 Raphael.js 的 getSubpath() 方法好多了。它确实完成了工作,但通常看起来更像是笔触从其原点向上缩放。
你好!
这很不错!
如果我在 html 中编写 svg,它可以工作,但如果我使用对象导入 svg,它就不起作用。
这能解决吗?
:*
如果你将你的 SVG 隐藏在一个
<object>
标签中,它将无法从 CSS 访问。你可以在外部 SVG 文件中包含 CSS 样式,但我不能保证这在所有 SVG 浏览器中都能工作。太好了!很棒的文章,一个问题:如何在动画完成后停止动画?
animation-fill-mode: forwards;
太棒了!非常感谢您提供这种快速易懂的解释!
非常感谢!它非常有用。
很棒!:)
提醒一下,并非所有浏览器都以相同的方式解释
stroke-dashoffset
属性,而且您定义动画的方式可能会导致意外结果。请查看 此 Stack Overflow 问答。我不确定在这些情况下偏移量是如何解释的,但 规范 并没有真正明确说明当虚线模式是封闭路径长度的两倍,并且您将模式偏移整个长度时应该发生什么。最终的效果是,一些浏览器将切换到零偏移量解释为从完全绘制的线变为无,而另一些浏览器则将其解释为从无变为完全绘制的线。如果您将动画设置为
alternate infinite
,这并不重要,但如果您想绘制线条并使其保持在那里,就会有很大区别。我建议使用
stroke-dasharray
属性完成整个动画。带有已实现更改的示例 Pen 的版本。
动画只进行一次。
是的,它可以制作出非常酷且简单的动画,尤其是在您的设计师喜欢矢量图形,并且除了 Adobe Illustrator 之外什么都不用的时候。
该值是“静态”的吗?也就是说,对于相同给定的路径,它是否总是保持不变?这样,只需使用 JS 一次获取其长度,然后就可以将该固定值放入 CSS 中(是的,我知道,这有点像“魔术数字”,但仍然)。
或者它是动态的,取决于…什么?浏览器、SVG 图像的显示尺寸…?
该长度以路径元素的坐标系单位给出,因此与 SVG 的整体缩放无关。但是,规范允许浏览器使用他们选择的算法估计确切长度,因此结果可能并不总是完全相同。为了控制这一点,您可以将路径元素上的“pathLength”属性设置为用于动画的值,浏览器应该相应地调整其计算结果。
换句话说,为了确保互操作性,您可以在开发计算机上使用 JavaScript 计算路径的长度,然后在路径元素上声明该长度作为
pathLength
属性,然后在您的 CSS 动画中安全地使用它,而不必担心在不同的浏览器上会略有偏差。您可以跳过计算,只将 pathLength 声明为一个您选择的漂亮的整数,但随后您需要进行一些深入的跨浏览器测试,以确保它们都进行了适当的计算…感谢 Amelia,也感谢您的其他评论,非常有用!
你好,
我重新创建了这个,我想在动画绘制完成后让它留在页面上。我该如何操作呢?我删除了无限,它只播放一次。我想让它留在页面上。
任何帮助都将不胜感激。
谢谢!
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
-webkit-animation: dash 5s linear;
-webkit-animation-iteration-count:1;
}
@-webkit-keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 10;
}
}
我不明白,为什么你需要 stroke-dashoffset: 1000; ?
你可以这样做
.path {
stroke-dasharray: 1000;
animation: dash 5s linear;
animation-fill-mode: forwards;
}
@keyframes dash {
from{
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
一些浏览器支持 SVG,但不支持线条动画(我指的是 IE)。
那么如何测试浏览器是否支持 SVG 线条动画,以便我可以回退到光栅图形呢?