Raphael JS:如何移动/动画化路径对象?

13

不知何故这并不起作用...

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);
});

我可以这样移动矩形,但不能移动路径,为什么呢?如何移动路径对象?!


1
你有在线示例吗,例如jsbin? - Adam Holmes
6个回答

33
使用最新版本的Raphael,您可以做到这一点:
var _transformedPath = Raphael.transformPath('M100 100L190 190', 'T400,0');
testpath.animate({path: _transformedPath}, 1000);

这样做可以避免你克隆一个临时对象的麻烦。

2
这是最正确的答案,因为它包含了Raphael的最新功能,并且只需两行代码即可解决。非常好用,谢谢。 - podcastfan88
2
我唯一要补充的是,如果你想得到一个真正的动画效果,你必须在第二个花括号后面加上一个速度参数,就像这样:({path: _transformedPath},1000); - podcastfan88
1
最佳答案在这里,而且是最简单的! - soyuka

18
似乎 path 对象没有得到 xy 值,因此您的动画可能仍在运行,但不起作用。尝试改为使用路径函数进行动画处理:
testpath.animate({path:'M400 100L490 190'},1000);

这使得编写动画变得有点棘手,但你可以免费获得旋转和缩放的好处!

顺便说一句:我确定这只是一个例子,但在你上面的代码中,testpath没有被初始化为var testpath,所以它被放在了全局作用域中。


10

感谢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();

});

你的意思是 var temp=testpath.clone(); 吧 ;) - Rudu
非常好。另一个答案完全忽略了你不想定义一个新路径来跳到侧面的事实。很好的建议。 - Joseph Lust

4

TimDog的答案是最佳解决方案。

此外,要记住,在这种情况下转换字符串意味着它将向每个路径点/线X坐标添加400个点,而对于每个Y坐标添加0个点。

这意味着M100 100L190 190将变成M500 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});

希望这能对某些人有所帮助。


2
这里有一些代码,可以概括上述答案的精华,并为Raphael路径提供一个简单的.attr({pathXY: [newXPos, newYPos]})属性,类似于.attr({x: newXPosition}).animate({x: newXPosition})用于形状。
这使您可以以标准方式将路径移动到固定的绝对位置相对移动量,而不需要硬编码路径字符串或自定义计算。
编辑:下面的代码适用于IE7和IE8。此前版本在IE8 / VML模式下失败,因为 Raphael bug会在SVG模式下向.attr('path')返回数组,但在VML模式下向.attr('path')返回字符串

代码

在定义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')]});
   }
};

使用方法

绝对定位翻译(移动至固定的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坐标,以便它们可以一起动画,并保持彼此同步。

相对平移(通过+/- X,Y移动)的翻译 - 实时JSBIN演示

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

这也适用于集合,但不要忘记Raphael的集合并不像组 - 每个对象移动到相对于集合的平均位置的一个位置,因此结果可能不是预期的(示例演示)。


用于动画(将路径移动到相对或绝对位置)

首次进行动画之前,您需要设置pathXY值,由于在Raphael 2.1.0之前存在错误/缺失功能,所有customAttributes在动画之前都需要给出数值(否则,它们会将每个数字转换为NaN并且什么也不做,没有错误静默失败,或者不进行动画并直接跳转到最终位置)。

在使用.animate({pathXY: [newX,newY]});之前,请运行此辅助函数:

somePath.pathXY();

0
另一种方法是使用“transform”属性:
testpath.animate({transform: "t400,0"}, 1000);

将路径相对于原始位置向右移动400像素。

这适用于所有形状,包括路径和矩形。

请注意:

  • “transform”属性与x、y、cx、cy等无关,因此这些属性不会被上述动画更新。
  • “transform”属性的值始终基于原始位置而非当前位置。如果您在上述动画之后应用下面的动画,则它将相对地向左移动800像素,而不是将其移动回原始位置。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接