web-dev-qa-db-ja.com

Raphael JS:パスオブジェクトを移動/アニメーション化する方法は?

どういうわけかこれは機能しません...

var paper = Raphael("test", 500, 500);

var testpath = paper.path('M100 100L190 190');

var a = paper.rect(0,0,10,10);
a.attr('fill', 'silver');

a.mousedown( function() {
  testpath.animate({x: 400}, 1000);
});

この方法で四角形を移動することはできますが、パスを移動することはできません。その理由と、パスオブジェクトを移動するにはどうすればよいですか。

12
Dylan

Raphaelの最新バージョンでは、次のことができます。

var _transformedPath = Raphael.transformPath('M100 100L190 190', 'T400,0');
testpath.animate({path: _transformedPath}, 1000);

これにより、一時オブジェクトをcloneする必要がなくなります。

29
TimDog

pathオブジェクトはxy値を取得していないようです。したがって、アニメーションはおそらく実行されますが、何も実行されません。代わりに、パス関数をアニメーション化してみてください。

testpath.animate({path:'M400 100L490 190'},1000);

アニメーションを書くのは少し難しいですが、回転とスケーリングを無料で利用できるという利点があります。

ところで:これは単なる例だと思いますが、上記のコードでは、var testpathとして初期化しないため、testpathがグローバルスコープに配置されます。

17
Rudu

解決しました、Ruduに感謝します!

アニメートする新しいパスを作成する必要があります。 clone()を使用してこれを実行し、そのクローンに変換を適用できます。このような単純な動きでは非常に複雑に見えますが、機能します...

var paper = Raphael("test", 500, 500);

var testpath = paper.path('M100 100L190 190');

var a = paper.rect(0,0,10,10);
a.attr('fill', 'silver');

a.mousedown( function() {

  var temp = testpath.clone();
  temp.translate(400,0);
  testpath.animate({path: temp.attr('path')}, 1000);
  temp.remove();

});
10
Dylan

TimDogの答えが最善の解決策でした。

さらに、この場合の変換文字列は、すべてのパスポイント/ラインX座標に400ポイントを追加し、すべてのY座標に0ポイントを追加することを意味することを覚えておいてください。

つまり、M100 100L190 190M500 100L590 190に変わります。

したがって、パス要素を別の位置に移動する必要がある場合は、現在の位置と新しい位置の座標の差を計算する必要があります。これを行うには、最初の要素を使用できます。

var newCoordinates = [300, 200],
curPos = testpath.path[0],
newPosX = newCoordinates[0] - curPos[1],
newPosY = newCoordinates[1] - curPos[2];

var _transformedPath = Raphael.transformPath(testpath.path, "T"+newPosX+","+newPosY);
testpath.animate({path: _transformedPath});

これが誰かを助けることを願っています。

4
Deele

上記の回答の最良のものを一般化し、Raphaelパスに単純な.attr({pathXY: [newXPos, newYPos]})形状の.attr({x: newXPosition}).animate({x: newXPosition})に似た属性を与えるコードを次に示します。

これにより、パス文字列やカスタム計算をハードコーディングせずに、標準的な方法でパスを固定の絶対位置または相対量だけ移動に移動できます。


編集:以下のコードはIE7およびIE8で機能します。これの以前のバージョンは、次の理由でIE8/VMLモードで失敗しました SVGモードでは配列を.attr( 'path')に返しますが、VMLモードでは文字列を.attr( 'path')に返すRaphaelバグ


コード

paperを定義した後、このコード( Raphael customAttribute 、およびヘルパー関数)を追加します。以下のように使用します。

paper.customAttributes.pathXY = function( x,y ) {
  // use with .attr({pathXY: [x,y]});
  // call element.pathXY() before animating with .animate({pathXY: [x,y]})
  var pathArray = Raphael.parsePathString(this.attr('path'));
  var transformArray = ['T', x - this.pathXY('x'), y - this.pathXY('y') ];
    return { 
      path: Raphael.transformPath( pathArray, transformArray) 
    };
};
Raphael.st.pathXY = function(xy) { 
   // pass 'x' or 'y' to get average x or y pos of set
   // pass nothing to initiate set for pathXY animation
   // recursive to work for sets, sets of sets, etc
   var sum = 0, counter = 0;
   this.forEach( function( element ){
     var position = ( element.pathXY(xy) );
     if(position){
       sum += parseFloat(position);
       counter++;
     }
   });
   return (sum / counter);
};
Raphael.el.pathXY = function(xy) {
   // pass 'x' or 'y' to get x or y pos of element
   // pass nothing to initiate element for pathXY animation
   // can use in same way for elements and sets alike
   if(xy == 'x' || xy == 'y'){ // to get x or y of path
     xy = (xy == 'x') ? 1 : 2;
     var pathPos = Raphael.parsePathString(this.attr('path'))[0][xy];
     return pathPos;
   } else { // to initialise a path's pathXY, for animation
     this.attr({pathXY: [this.pathXY('x'),this.pathXY('y')]});
   }
};

使用法

絶対変換の場合(move to固定X、Y位置) ライブJSBINデモ

任意のパスまたは セットのセット(デモ)を含むパスのセット で動作します。 Raphaelセットはグループではなく配列であるため、セット内の各アイテムを、セットの中心ではなく、定義された位置に移動することに注意してください。

// moves to x=200, y=300 regardless of previous transformations
path.attr({pathXY: [200,300]});

// moves x only, keeps current y position
path.attr({pathXY: [200,path.pathXY('y')]});

// moves y only, keeps current x position
path.attr({pathXY: [path.pathXY('x'),300]});

Raphaelは、x座標とy座標の両方を同じcustomAttributeで一緒に処理して、一緒にアニメーション化できるようにし、互いに同期を保つ必要があります。

相対変換の場合(move by +/- X、Y) Live JSBIN demo

// moves down, right by 10
path.attr({pathXY: [ path.pathXY('x')+10, path.pathXY('y')+10 ]},500);

これはセットでも機能しますが、ラファエルのセットはグループのようではないことを忘れないでください-各オブジェクトはセットの平均位置に対して1つの位置に移動するため、結果が期待どおりにならない場合があります( 例デモ )。


アニメーションの場合(パスを相対位置または絶対位置に移動します)

初めてアニメーション化する前に Raphael 2.1.0までのバグ/欠落機能のため、pathXY値を設定する必要があります。これは、アニメーション化する前にすべてのcustomAttributesに数値を指定する必要があるためです(そうでない場合)。 、すべての数値をNaNに変換して何もせず、エラーなしでサイレントに失敗するか、アニメーション化して最終位置に直接ジャンプしません)。

.animate({pathXY: [newX,newY]});を使用する前に、次のヘルパー関数を実行してください。

somePath.pathXY();
2
user568458

さらに別の方法は、「変換」属性を使用することです。

testpath.animate({transform: "t400,0"}, 1000);

パスを元の位置に対して400px右に移動します。

これは、パスや長方形を含むすべての形状で機能するはずです。

ご了承ください:

  • 「変換」属性は、x、y、cx、cyなどから独立しています。したがって、これらの属性は上記のアニメーションでは更新されません。
  • 「変換」属性の値は、現在の位置ではなく、常に元の位置に基づいています。上のアニメーションの後に下のアニメーションを適用すると、元の位置に戻すのではなく、比較的左に800px移動します。

    testpath.animate({transform: "t-400,0"}, 1000);
    
0