如果你看不到这个演示, 说明你的浏览器不支持 SVG, 请使用最新版的谷歌浏览器或火狐浏览器.
我喜欢用图画, 图表来演示流程信息或浏览器的操作过程, 但大量的图片有时候也会很不方便. 在我的一个关于应用缓存和缓存方法 http://vimeo.com/69385032 的演讲中, 我让屏幕首先空白, 然后各种图表按照我的演讲内容自己一点一点的画出来 http://vimeo.com/69385032#t=4m15s . 下面就是我如何用 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 http://inkscape.org/ 软件来画 SVG 图, 但它产生的 SVG 文件完全不可读, 而且有很多冗余代码, 但在你编辑的时候, 它会提供一个 SVG DOM 视图. 相比起 Adobe Illustrator 使用自己的格式, 仅提供 SVG 格式导出, 我更愿意使用前者.
属性 d 里的每一部分都是告诉浏览器生成一个动作 -- 移动到某一个点, 开始画一条线, 画一个贝齐尔弧线, 等等.
关于这些数据是如何变成动画, 变成一条慢慢画出的线, 这是个非常复杂的问题, 幸运的是, 我们不用考虑这些. 我可以使用颜色和设置点的宽度, 让 SVG 路径变成一段一段的点线, 并控制点的偏移量:
- <path stroke="#000" stroke-width="4.3" fill="none" d="..." stroke-dasharray=""
- stroke-dashoffset="" />
如果你看不到这个演示, 说明你的浏览器不支持 SVG, 请使用最新版的谷歌浏览器或火狐浏览器.
属性 stroke-dasharray 是让你指定画出的线段每段的长度, 第二个值是各段之间空隙的长度. 属性 stroke-dashoffset 是让你指定每个小段的起始偏移量.
请将两个游标都拖到最大值, 然后缓慢的减少 dashoffset 属性值. 哇塞, 线被动态的画出来了! 线的长度你可以从 DOM 里获取:
- var path = document.querySelector('.squiggle-container path');
- path.getTotalLength();
让线自动画出
在 SVG 里运用动画的最简单的方法是使用 CSS animations 或 transition. 但有一点问题, 在 IE 里不好用, 如果你想在 IE 里实现, 你需要使用, 并用 JavaScript 一帧一帧的修改里面的值.
最好别使用 SMIL,IE 不支持它而在谷歌浏览器和 Safari 里也有性能问题.
我打算使用 CSS transitions, 所以, 这个演示无法在 IE 里运行. 而且我无法找到一个好用的方法检测你的 IE 是否已经支持了这些 SVG 元素上的动画, 因为 IE 里能检测到所有的 SVG 属性, 但就是不能用.
在前面的例子中, 我们用 SVG 里的属性定义了小短线, 其实我们可以用 CSS 做相同的事情. SVG 里各种属性在功能上是和 CSS 属性完全相同的 http://www.w3.org/TR/SVG/styling.html .
- var path = document.querySelector('.squiggle-animated path');
- var length = path.getTotalLength();
- // 清除之前的动作
- path.style.transition = path.style.webkitTransition =
- 'none';
- // 设置起始点
- path.style.strokeDasharray = length + ' ' + length;
- path.style.strokeDashoffset = length;
- // 获取一个区域, 获取相关的样式, 让浏览器寻找一个起始点.
- path.getBoundingClientRect();
- // 定义动作
- path.style.transition = path.style.WebkitTransition =
- 'stroke-dashoffset 2s ease-in-out';
- // Go!
- path.style.strokeDashoffset = '0';
动起来!
如果你看不到这个演示, 说明你的浏览器不支持 SVG, 请使用最新版的谷歌浏览器或火狐浏览器.
使用 getBoundingClientRect 来获取一个区域, 虽然不是很好的做法, 但好用. 但有个问题是, 如果你在同一个 JavaScript 执行里修改一个样式两次而没有强制更新这个区域, 那只有最后一次有效.
我通常通过获取 offsetWidth 来找到 SVG 范围, 但在火狐里好像不灵.
更多有趣的实现
Lea Verou http://lea.verou.me/ 使用相同的技术创建了一个加载动画 http://dabblet.com/gist/6089395 .Josh Matz https://twitter.com/joshmatz 和 El Yosh https://twitter.com/El_Yosh 在他的基础上创建了这个有趣的立方体动画 http://dabblet.com/gist/6089409 .
我们已经使用 stroke-dasharray 属性创建了虚线动画, 实际上我们可以使用这种技术创建出更复杂的效果. 例如, 下面是贾斯汀比伯的签名, 看起来有点像莫尔斯电码:
(英文: Animated line drawing in SVG.)
来源: http://www.webhek.com/post/animated-line-drawing-in-svg.html