如何逐步绘制vectorpath? (Raphael.js)

如何animation像绘制的vectorpath,逐步? 换句话说,逐个像素缓慢地显示path。

我正在使用Raphaël.js但是如果你的答案不是库特定的,比如说可能有一些用于做这种事情的一般编程模式(我对vectoranimation相当陌生),这是值得欢迎的!


使用直线path很容易,就像在该页面上的示例一样简单::

 path("M114 253").animate({path: "M114 253 L 234 253"}); 

但是尝试改变那个页面上的代码,这样说:

 path("M114 26").animate({path: "M114 26 C 24 23 234 253 234 253"}); 

你会明白我的意思 path肯定是从初始状态(点“M114 26”)到结束状态(从点“M114 26”开始的曲线“C 24 23 234 253 234 253”)animation的,但不是以问题指定的方式,而不是它正在绘制。

我不明白animateAlong如何做到这一点。 它可以沿着一条pathanimation一个物体,但是如何让这条path在物体沿着它被animation的时候逐渐显示出来呢?


解决scheme?

(通过陨石的答案 )

似乎目前最好的方法是通过使用原始SVG的“虚假”破折号。 有关解释,请参阅本演示或本文档 ,第4页。

如何产生渐进式绘画?

我们必须使用stroke-dasharraystroke-dashoffset并且知道曲线的长度。 此代码在屏幕上为圆,椭圆,折线,多边形或path绘制任何内容:

 <[element] style="stroke-dasharray:[curve_length],[curve_length]; stroke-dashoffset:[curve_length]"/> 

如果在animation元素stroke-dashoffset减less到0,我们得到曲线的渐进绘制。

 <circle cx="200" cy="200" r="115" style="fill:none; stroke:blue; stroke-dasharray:723,723; stroke-dashoffset:723"> <animate begin="0" attributeName="stroke-dashoffset" from="723" to="0" dur="5s" fill="freeze"/> </circle> 

如果你知道更好的方法,请留下一个答案。


更新 (2012年4月26日):find一个很好地说明这个想法的例子,参见animationBézier曲线 。

我为此创build了一个脚本: Scribble.js ,基于这个伟大的dasharray/dashoffset技术 。

只是实例化了一堆SVG <path> s:

 var scribble = new Scribble(paths, {duration: 3000}); scribble.erase(); scribble.draw(function () { // done }); 

NB:完整的USAGE代码在这里: https : //gist.github.com/abernier/e082a201b0865de1a41f#file-index-html-L31

请享用 ;)

也许有人正在寻找一个答案,像我现在两天:

 // Draw a path and hide it: var root = paper.path('M0 50L30 50Q100 100 50 50').hide(); var length = root.getTotalLength(); // Setup your animation (in my case jQuery): element.animate({ 'to': 1 }, { duration: 500, step: function(pos, fx) { var offset = length * fx.pos; var subpath = root.getSubpath(0, offset); paper.clear(); paper.path(subpath); } }); 

这对我来说只是通过使用RaphaelJS方法。

这是一个jsFiddle的例子,在评论请求, http://jsfiddle.net/eA8bj/

find了! (也许 – 假设你很舒服地走出了拉斐尔的友好境界,进入纯SVG领域……)

您可以使用SVG keyTimeskeySplines

这是一个工作的例子:

http://www.carto.net/svg/samples/animated_bustrack.shtml

…这里有一些可能有用的解释:

http://msdn.microsoft.com/en-us/library/ms533119(v=vs.85).aspx

我想提供一个替代,拉斐尔+ JS的解决scheme,我已经在我自己的工作中大量使用。 它比davidenke的解决scheme有几个优点:

  1. 每个循环都不清除纸张,使animationpath与其他元素很好地共存;
  2. 重复使用拉斐尔自己的渐进式animation的单一path,使animation更stream畅;
  3. 大大减less资源密集。

这里的方法(可以很容易地重新组成一个扩展):

 function drawpath( canvas, pathstr, duration, attr, callback ) { var guide_path = canvas.path( pathstr ).attr( { stroke: "none", fill: "none" } ); var path = canvas.path( guide_path.getSubpath( 0, 1 ) ).attr( attr ); var total_length = guide_path.getTotalLength( guide_path ); var last_point = guide_path.getPointAtLength( 0 ); var start_time = new Date().getTime(); var interval_length = 50; var result = path; var interval_id = setInterval( function() { var elapsed_time = new Date().getTime() - start_time; var this_length = elapsed_time / duration * total_length; var subpathstr = guide_path.getSubpath( 0, this_length ); attr.path = subpathstr; path.animate( attr, interval_length ); if ( elapsed_time >= duration ) { clearInterval( interval_id ); if ( callback != undefined ) callback(); guide_path.remove(); } }, interval_length ); return result; } 

这里有两个在我的网站上的使用样本:一个用于path转换 ,另一个用于渐进式刻字 。

使用“ pathLength ”属性,我们可以将虚拟长度设置为path。 从那时起,我们可以在“stroke-dasharray”中使用这个虚拟长度。 因此,如果我们将“pathLength”设置为100个单位,那么我们就可以将“stroke-dasharray”设置为“50,50”,这完全是path的50%,50%!

这种方法有一个问题:唯一支持这个属性的浏览器是Opera 11。

下面是没有JavaScript或硬编码长度的平滑曲线绘制animation的例子(只适用于Opera 11)

当path变得复杂的时候,Anton和Pepepepeter的解决scheme在Chrome中出现问题。 这个链接的演示中的巴士地图是好的。 看看这个我创build的animation“花瓣”jsfiddle,它在FF10和Safari5中正确绘制,但在Chrome中无法控制闪烁:

http://jsfiddle.net/VjMvz/

(这是所有的HTML和内联SVG,没有JavaScript。)

我仍然在寻找一个非Flash解决scheme。 AnimateAlong显然不会因为我所做的而削减它。 Raphael.js可以工作,但它可能会很快变成回拨意大利面。

Davidenke,你可以发表你的解决scheme工作jsfiddle吗? 我只是不能得到它的工作。 我在Chrome 18中遇到错误,使用“.hide”设置为“display:none”的节点没有方法“getTotalLength”。

不幸的是,你似乎同意,你可能无法在拉斐尔优雅地做到这一点。

但是 ,如果你通过%deity%的某种方法不需要支持IE,那么你可以放弃Raphael API, 直接操纵SVG 。 然后,也许,你可以戴上面具沿着小路骑行,并以自然的速度显露出线条。

您可以在IE中优雅地降级,只需使用Raphael显示path,而无需animation。

我只是在做这个。 我尝试的第一件事是安东的解决scheme,但performance糟透了。

最后,获得我想要的结果的最简单方法是使用animation函数的替代“关键帧”语法。

通过getSubpath循环生成一大堆关键帧。

创build一个可见的新path并等于第一个关键帧。

然后做一些事情:

path.anmimate({keyFrameObject,timeframe});

您不需要为要绘制的每个像素都设置一个关键帧。 在玩过参数之后,我发现每个关键帧的值为100px,对于我想要“绘制”的复杂性/大小,

只是更新,你可以尝试懒线画家

你试过Raphael的animateAlong吗? 您可以在演示页面上看到它的动作。

好的,这是我的想法…这个解决scheme离理想太远了。

要逐渐显示path的意思,我们应该像逐点显示一样。 而vectorpath不是由点组成的,而是由曲线构成的,所以在我看来,在vectorgraphics中逐渐“画出”path是没有“自然”的方式的。 (虽然我对此很新,可能是错的。)

唯一的办法是以某种方式将path转换为多个点并逐一显示。

目前我的解决方法是绘制一条path,使其不可见,将其分解成多个子path,并逐个显示子path。

这与拉斐尔并不难,但也不是很优雅,而且在很大的路上很慢。 不接受我的答案,希望有更好的办法…