SVG技术入门:线条动画实现原理
相信大家都见到过这样神奇的技术:一副线条构成的画能自动画出自己。非常的酷。Jake Archibald是这种SVG技术的首创者,并且写了一篇非常好的文章来描述它是如何实现的。Brian Suda也在24 Ways网站上讨论过它。 Polygon使用它在一篇设计方面的文章里创造出了非常神奇的效果。Codrops也做出了一些非常漂亮的例子
其实我没有什么好增补的,只是想把这种技术说的更明白些,所以,在这里我要用我的方式把这种技术再讲解一遍。
1. 你有一个SVG图形
2. 这个图形必须要有一个线条(stroke)属性
3. 线条可以是虚线
我们可以用Illustrator制作,也可以用编程实现。我们用CSS来设置这些路径的样式(假定我们这里是inline SVG,或通过一个<object>),把它们变成虚线形式。
<svg ...>    <path class="path" stroke="#000000" ... >  </svg>
.path {
  stroke-dasharray: 20;
}
这是让虚线里的每个小线段长度为20px。
4. 可以让虚线小段的长度变得更长….
.path {
  stroke-dasharray: 100;
}
5. 我们还可以给我们的线条设置”offset”偏移量,这样会导致虚线里的小线段的位置发生移动。
当我们动态设置图形中线条的“offset”值时,可以看到这个效果:

可以这样简单的实现:
.path {
  stroke-dasharray: 100;
  animation: dash 5s linear;
}
@keyframes dash {
  to {
    stroke-dashoffset: 1000;
  }
}
6. 想象,当虚线的小线条足够长,超过图形的整个线条长度时
没有什么变化,整个图像看起来完全不是虚线。你只需要将stroke-dasharray属性设置的足够长,超过整个线条的长度。
7. 现在给线条设置偏移量,让它不再覆盖整个图形。
这样你就看不见图形了。
8. 现在动态的慢慢将线条的偏移量设置回归到0

如果通过CSS,你需要将animation属性设置成forwards,这样整个动画就会停止在它的最终状态。
.path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 5s linear forwards;
}
@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}
Tada!
实例演示
 
为什么要用JavaScript?
大部分你看到的SVG线条动画都使用了JavaScript。这是因为在现实情况中你很难知道线条有多长。我们这里设置的是1000,是因为它碰巧是1000。
用JavaScript获取长度值的写法是这样的:
var path = document.querySelector('.path');
var length = TotalLength();
然后你就可以随便使用这个值了。文本顶部链接的那些文章讲的都比本文透彻,你最好还是参考一下那些文章。我只想简单的讲一下这种技术方法,希望它能给你一些启示。
SVG技术入门:如何画出一条会动的线
我喜欢用图画、图表来演示流程信息或浏览器的操作过程,但大量的图片有时候也会很不方便。在我的一个关于应用缓存缓存方法的演讲中,我让屏幕首先空白,然后各种图表按照我的演讲内容自己一点一点的画出来。下面就是我如何用SVG技术在浏览器里实现这种效果
的。
SVG里的路径(path)
SVG里用来定义路径的格式堪比正则表达式的怪异:
<path fill="none" stroke="deeppink" stroke-width="14" stroke-miterlimit="0"
d="M11.6 269s-19.7-42.4 6.06-68.2 48.5-6.06 59.1 12.1l-3.03 28.8 209-227s45.5-21.2 60.6 1.52c15.2 22.7-3.03 47-3.03 47l-225 229s33.1-12 48.5 7.58c50 63.6-50 97-62.1 37.9"
/>
我通常是使用Inkscape软件来画SVG图,但它产生的SVG文件完全不可读,而且有很多冗余代码,但在你编辑的时候,它会提供一个SVG DOM视图。相比起Adobe Illustrator使用自己的格式、仅提供SVG格式导出,我更愿意使用前者。
属性d里的每一部分都是告诉浏览器生成一个动作——移动到某一个点,开始画一条线,画一个贝齐尔弧线,等等。
关于这些数据是如何变成动画,变成一条慢慢画出的线,这是个非常复杂的问题,幸运的是,我们不用考虑这些。我可以使用颜和设置点的宽度,让SVG路径变成一段一段的点线,并控制点的偏移量:
 
<path stroke="#000" stroke-width="4.3" fill="none" d="…"
stroke-dasharray=""
stroke-dashoffset="0.00"
/>
属性dasharray:
属性dashoffset:
属性stroke-dasharray是让你指定画出的线段每段的长度,第二个值是各段之间空隙的长度。属性stroke-dashoffset是让你指定每个小段的起始偏移量。
请将两个游标都拖到最大值,然后缓慢的减少dashoffset属性值。哇塞,线被动态的画出来了!线的长度你可以从DOM里获取:
var path = document.querySelector('.squiggle-container path'); TotalLength();
让线自动画出
在SVG里运用动画的最简单的方法是使用CSS animations或transition。但有一点问题,在IE里不好用,如果你想在IE里实现,你需要使用requestAnimationFrame,并用JavaScript一帧一帧的修改里面的值。
最好别使用SMIL,IE不支持它而在谷歌浏览器和Safari里也有性能问题。
我打算使用CSS transitions,所以,这个演示无法在IE里运行。而且我无法到一个好用的方法检测你的IE是否已经支持了这些SVG元素上的动画,因为IE里能检测到所有的SVG属性,但就是不能用。
在前面的例子中,我们用SVG里的属性定义了小短线,其实我们可以用CSS做相同的事情。html animation属性SVG里各种属性在功能上是和CSS属性完全相同的
var path = document.querySelector('.squiggle-animated path'); var length = TotalLength(); // 清除之前的动作 ansition = path.style.WebkitTransition = 'none'; // 设置起始点 path.style.strokeDasharray = length + ' ' + length; path.style.strokeDashoffset = length; // 获取一个区域,获取相关的样式,让浏览器寻一个起始点。 BoundingClientRect(); // 定义动作 ansition = path.style.WebkitTransition = 'stroke-dashoffset 2s ease-in-out'; // Go! path.style.strokeDashoffset = '0';
 
 
使用getBoundingClientRect来获取一个区域,虽然不是很好的做法,但好用。但有个问题是,如果你在同一个JavaScript执行里修改一个样式两次而没有强制更新这个区域,那只有最后一次有效。
我通常通过获取offsetWidth来到SVG范围,但在火狐里好像不灵。
更多有趣的实现
Lea Verou使用相同的技术创建了一个加载动画Josh Matz 和 El Yosh 在他的基础上创建了这个有趣的立方体动画
我们已经使用stroke-dasharray属性创建了虚线动画,实际上我们可以使用这种技术创建出更复杂的效果。例如,下面是贾斯汀比伯的签名,看起来有点像莫尔斯电码: