如何逐步绘制矢量路径?(拉斐尔.js)

IT技术 javascript animation vector svg bezier
2021-02-24 00:00:53

如何逐步动画矢量路径就像它正在绘制一样?换句话说,慢慢地逐个像素地显示路径。

我正在使用Raphaël.js如果您的答案不是特定于库的——比如可能有一些通用的编程模式来做那种事情(我对矢量动画相当陌生)——欢迎!


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

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

但是尝试更改该页面上的代码,例如:

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

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

我不明白怎么animateAlong能做到这一点。它可以沿路径为对象设置动画,但是如何在对象沿路径设置动画时使该路径逐渐显示自身?


解决方案?

(通过peteorpeter 的回答。)

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

如何制作渐进式绘图?

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

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

如果动画元素中的stroke-dashoffset 减少到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 日):找到一个很好地说明这个想法的例子,请参阅动画贝塞尔曲线

6个回答

也许有人正在寻找答案,就像我这两天一样:

// 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/

在我的情况下它非常顺利。但是我还没有在不同的浏览器中测试过那么多......结合jquery中的一些缓动方程,它非常强大(对于我的单一路径......)。
2021-04-28 00:00:53
干得好!正在寻找解决方案,多亏了你,我只花了一个小时!
2021-04-28 00:00:53
如果有人能把它放在 jsfiddle 中会很好,因为我很难让它工作,不可否认,我是 Raphael 的新手。
2021-04-28 00:00:53
我对您的 jsFiddle 进行了一些调整,因此它与单个 raphael 路径元素隔离:http : //jsfiddle.net/eA8bj/63/
2021-05-03 00:00:53
是的 - 这实际上就是我在我的答案中所说的“绘制路径,使其不可见,将其分解为多个子路径,并一个一个地显示子路径”的意思,但感谢您用代码进行解释。=) 我不太喜欢这个解决方案,因为它不是很顺利,而且可能需要资源。
2021-05-06 00:00:53

尤里卡!(也许 - 假设你很舒服地走出 Raphael 的友好领域进入纯 SVG 领域......)

您可以使用 SVG keyTimeskeySplines

这是一个工作示例:

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

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

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

看起来 SVGweb 可能支持这个 SVG 特性,这意味着通过 flash 获得更好的 IE 支持和性能:code.google.com/p/svgweb/source/browse/trunk/src/org/svgweb/...
2021-04-17 00:00:53
哇,看着演示......我想这是目前最好的方式!我现在无法理解所有带有破折号的操作,所以我自己还没有尝试过。此外,第一个链接中的站点看起来像是一个很好的 SVG 资源。附注。Raphael 的领域不仅友好,而且生成的图形可以在 IE6 上运行(尽管性能不佳)。可悲的是,这有时很重要。
2021-05-08 00:00:53

我想提供一个替代的、仅限 Raphael+JS 的解决方案,我在自己的工作中大量使用了该解决方案。与 davidenke 的解决方案相比,它有几个优点:

  1. 不会在每个循环中清除纸张,允许动画路径与其他元素很好地共存;
  2. 使用 Raphael 自己的渐进动画重复使用单个路径,使动画更流畅;
  3. 资源密集程度大大降低。

这是方法(可以很容易地将其重组为扩展):

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 Transformation,另一个用于Progressive Lettering

这是一个很好的解决方案凯文。这里需要一个建议,当逐渐绘制线条时,即使我将strokelinecap 和strokelinejoin 指定为圆形,最后绘制的线条也在对接帽中。如果您对此有任何解决方案,请告诉我。如果我尝试在数组的最后一个索引中用 z 关闭线,则该线的最后一个点与该线的起点相连
2021-04-22 00:00:53
感谢答案末尾的两个演示,这是一个很大的帮助。
2021-04-24 00:00:53

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

只需在一堆 SVG 上实例化它<path>

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

——

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

享受 ;)

哇,真是太棒了。感谢分享!
2021-04-25 00:00:53
是的,我认为至少现在应该选择它,作为现成的解决方案。
2021-05-03 00:00:53
欢迎@AntonStrogonoff ;)如果您认为它可以帮助他人并推广它,请随时回答;)
2021-05-06 00:00:53

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

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

是没有 javascript 或硬编码长度的平滑曲线绘制动画的示例。(仅在 Opera 11 中正常工作)

对 pathLength 的支持现在在 FF 中(从 v6 开始)。铬还没有。
2021-05-06 00:00:53