web-dev-qa-db-ja.com

ベクトルパスを段階的に描画する方法は? (Raphael.js)

描画されているようにベクターパスを徐々にアニメーション化する方法は?つまり、ピクセルごとにパスをゆっくり表示します。

Raphaël.jsbutを使用しています。答えがライブラリ固有ではない場合(たとえば、そのようなことを行うための一般的なプログラミングパターンがあるかもしれません(私はベクターアニメーションにかなり慣れていません))—どういたしまして!


そのページ ::の例のように簡単に、直線パスを使用して簡単にできます。

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")から終了状態(ポイント "M114 26"で始まる曲線 "C 24 23 234 253 234 253")までアニメーション化されていますが、問題の指定された方法ではなく、描かれています。

animateAlongがそれをどのように実行できるかわかりません。パスに沿ってオブジェクトをアニメーション化できますが、オブジェクトがそれに沿ってアニメーション化されている間、このパスを徐々に表示して自分自身を徐々に表示するにはどうすればよいですか?


ソリューション?

(via peteorpeter's answer 。)

現在それを行うための最良の方法のようですが、生の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日):アイデアをよく説明する例が見つかりました。 アニメーションベジエ曲線 を参照してください。

31

このスクリプトを作成しました: Scribble.js 、この素晴らしい dasharray/dashoffsetテクニック に基づいています。

一連のSVG <path>sをインスタンス化するだけです。

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

-

注:ここに完全なUSAGEコード: https://Gist.github.com/abernier/e082a201b0865de1a41f#file-index-html-L31

楽しい ;)

5
abernier

たぶん誰かが私のように答えを探しています。

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

26
davidenke

ユーレカ! (たぶん-あなたがラファエルの友好的な領域の外に純粋なSVGの土地に足を踏み入れて快適であると仮定します...)

SVGkeyTimesおよびkeySplinesを使用できます。

これが実際の例です:

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

...そしてここにいくつかの潜在的に有用な説明があります:

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

17
peteorpeter

私が自分の仕事でかなり使用した代替の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;
}

そして、これが私のサイトでの使用法の2つのサンプルです。1つは Path Transformation 用で、もう1つは Progressive Lettering 用です。

11
Kevin Nielsen

" pathLength "属性を使用して、仮想の長さをパスに設定できます。それ以降、この仮想の長さを「ストロークダッシュ配列」で使用できます。したがって、 "pathLength"を100単位に設定すると、 "stroke-dasharray"を "50,50"に設定できます。この場合、パスの50%、50%になります。

このアプローチには1つの問題があります。この属性をサポートするブラウザはOpera 11。

ここ は、JavaScriptまたはハードコードされた長さのない滑らかな曲線の描画アニメーションの例です(Opera 11)でのみ正しく機能します)

6
Brazhnyk Yuriy

Anton&Peteorpeterのソリューションは、Chromeでパスが複雑になると悲しいことに壊れます。リンクされたデモのバスマップには問題ありません。私が作成したこのアニメーション「花びら」jsfiddleをチェックしてください。正しく描画されます。 FF10とSafari5ですが、Chromeでは制御不能にちらつきます。

http://jsfiddle.net/VjMvz/

(これはすべてHTMLおよびインラインSVGであり、javascriptではありません。)

このための非フラッシュソリューションをまだ探しています。 AnimateAlongは、明らかに私がやっていることには対応できません。 Raphael.jsは機能する可能性がありますが、非常に高速にコールバックスパゲッティに変わると脅されています。

Davidenke、あなたのソリューションで動作するjsfiddleを投稿できますか?うまく動かないのです。 Chrome 18でエラーが発生します。「。hide」で「display:none」に設定されているノードには、「getTotalLength」メソッドがありません。

3
Ben

残念ながら、あなたが同意しているように見えるかもしれませんが、Raphaelではこれを上品に行うことはできません。

ただし%deity%のストロークにより、IEをサポートする必要がない場合特定の機能として、Raphael APIと SVGを直接操作する を忘れる可能性があります。次に、 mask をリグしてパスに沿って走り、自然なラインでラインを明らかにすることができますペース。

IEで優雅に低下させ、Raphaelを使用してパスをアニメーションなしで単に表示することができます。

2
peteorpeter

私はまさにこれをやっていた。私が最初に試みたのはアントンのソリューションでしたが、パフォーマンスはひどいものでした。

結局、私が望んでいた結果を得る最も簡単な方法は、アニメーション関数に代替の「キーフレーム」構文を使用することでした。

最終的なパスを目に見えない形で描画し、ループでgetSubpathを使用して一連のキーフレームを生成します。

表示され、最初のキーフレームと等しい新しいパスを作成します。

次に、次のようなことを行います:

path.anmimate({keyFrameObject、timeframe});

描画したいすべてのピクセルにキーフレームは必要ありません。パラメータをいじった後、キーフレームあたり100pxの値が、「描画」しようとしているものの複雑さ/サイズに効果的であることがわかりました

1
David Meister

これを更新するだけで、 Lazy Line Painter を試すことができます

1
JackSD

さてさて、これについての私の考えは…解決策は理想からかけ離れています。

パスの意味を徐々に表示するには、ドットごとに表示する必要があります。また、ベクターパスはドットではなく曲線で構成されているため、ベクターグラフィックでパスを徐々に「描く」のは「自然な」方法ではないように見えます。 (私はこれにかなり新しいので、間違っているかもしれませんが。)

唯一の方法は、パスをいくつかのドットに変換して、1つずつ表示することです。

現在の私の回避策は、パスを描画して非表示にし、それをいくつかのサブパスに分割して、そのサブパスを1つずつ表示することです。

これはRaphaelで行うのは難しくありませんが、エレガントでもないため、大きなパスではかなり遅くなります。私の答えを受け入れず、もっと良い方法があるといいのですが…

0

ラファエルの animateAlong を試しましたか?あなたはそれを実際に見ることができます デモページで

0