1

1 つのパスの単純なアニメーションは、いくつかのカスタム アトリビュートを使用してかなり簡単に作成できます。

(function() {
  Raphael.fn.addGuides = function() {
    this.ca.guide = function(g) {
      return {
        guide: g
      };
    };
    this.ca.along = function(percent) {
      var box = this.getBBox( false );
      var g = this.attr("guide");
      var len = g.getTotalLength();
      var point = g.getPointAtLength(percent * len);
      var t = {
        transform: "...t" + [point.x - box.x, point.y - box.y]
  };
  return t;
    };
  };
})();

var paper = Raphael("container", 600, 600);

paper.addGuides();

var circ1 = paper.circle(50, 50, 40);
var circ2 = paper.circle(150, 50, 40);
var circ3 = paper.circle(250, 50, 40);
var circ4 = paper.circle(350, 50, 40);

var redarc = "M200,100 c 22-7,37,5,38,9";
var redarcpath = paper.path(redarc).attr({'stroke-width': '2', 'stroke': 'red'});

circ3.attr({guide : redarcpath, along : 1})
         .animate({along : 0}, 2000, "linear");

参照: http://jsfiddle.net/p6Q3x/1/

ただし、セットに対して同じanimateメソッドを呼び出すと、セット内の要素の相対的な位置が崩れます。たとえば、この「ターゲット」の同心円はすべて、セットのバウンディング ボックスの左上に重なり合っています。

paper.setStart();
var inner = paper.circle(50, 250, 15);
var middle = paper.circle(50, 250, 30);
var outer = paper.circle(50, 250, 45);
var target = paper.setFinish();

var redarc = "M200,100 c 22-7,37,5,38,9";
var redarcpath = paper.path(redarc).attr({'stroke-width': '2', 'stroke': 'red'});

// basic animation of target on red arc collapses the shapes
target.attr({guide : redarcpath, along : 1})
         .animate({along : 0}, 2000, "linear");

参照: http://jsfiddle.net/p6Q3x/3/

メソッド内の小文字の相対 "t" は、along相対位置が保持されることを示唆しているため、これは奇妙です。しかし、いいえ。そこで、セットの各要素のモーション パスのクローンを作成し、セットのバウンディング ボックス内の「子」パスの相対位置に応じて、これらのクローン パスのそれぞれに異なる変換を適用しました。しかし、パスがアニメーションに使用される場合、変換マトリックスは無視されるため、それでも十分ではありません。そのため、変換された各モーション パスを生のパス データに「平坦化」する必要があります。ここでは、平坦化部分にティモの関数を使用しました。

function animateSet(set, pathToFollow) {
    var setBBox = set.getBBox(false);

    set.forEach(function (el) {
        var pathBBox = el.getBBox( false );
        
        // get the difference between the element's BBox
        // and its "parent" set's BBox coordinates
        var offset = "...t" + [pathBBox.x - setBBox.x, pathBBox.y - setBBox.y];
        
        // use offset to create a new, unique, displaced motion path
        var transformedPath = pathToFollow.clone()
                                          .hide()
                                          .transform(offset);
        
        // flatten that transformation back into raw path data
        var flatPathString = flatten_transformations(transformedPath, normalize_path, to_relative, dec);
        
        // and make a new Raphael path array out of that flattened data
        var shiftedPath = paper.path(flatPathString).hide();
        
        el.attr({guide : shiftedPath, along : 1})
          .animate({along : 0}, 2000, "linear", function() {
              transformedPath.remove(); // wipe out temporary motion paths
              shiftedPath.remove(); // when animation completes
        });
    });
}

良いニュースは、それが機能することです!http://jsfiddle.net/p6Q3x/

しかし、これは本当に醜く、肥大化し、動きが鈍く感じます。これがそれほど複雑になる必要があるとは信じられません。誰でも初心者に、よりシンプルでクリーンで効率的な方法を提案できますか? セットのメンバーがそれぞれ独自のバウンディング ボックスを取得できるように、セットの Along メソッドを書き直す必要があるというのが私の感覚ですが、それを正確に行う方法については途方に暮れています。すべてのヘルプは非常に感謝しています。

4

0 に答える 0