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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6282171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:05:25  来源:igfitidea点击:

Raphael JS : how to move/animate a path object?

javascriptanimationpathraphaelmove

提问by Dylan

Somehow this doesn't work...

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

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

I can move rects this way but not paths, why is that, and how do I move a path object then?!

我可以通过这种方式移动矩形而不是路径,为什么会这样,然后我如何移动路径对象?!

回答by TimDog

With the latest version of Raphael, you can do this:

使用最新版本的 Raphael,您可以执行以下操作:

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

This saves you from the trouble of having to clonea temp object.

这使您免于必须clone使用临时对象的麻烦。

回答by Rudu

It seems a pathobject doesn't get a x,yvalue - so your animation probably still runs, but does nothing. Try instead animating the path function:

似乎path对象没有获得x,y值 - 所以您的动画可能仍在运行,但什么也不做。尝试为路径函数设置动画:

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

It makes it a bit trickier to write the animation, but you have the benefit of getting rotation and scaling for free!

它使编写动画变得有点棘手,但您可以免费获得旋转和缩放!

BTW: I'm sure this is just an example, but in your above code testpathgets put in the global scope because you don't initialize as var testpath

顺便说一句:我确定这只是一个例子,但在你上面的代码testpath中,因为你没有初始化为var testpath

回答by Dylan

Solved, with thanx to Rudu!

解决了,感谢Rudu!

You need to create a new path to animate to. You can do this with clone() and then apply the transformations to that clone. Seems very complex for a simple move like this, but it works...

您需要创建一个新路径来制作动画。您可以使用 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();

});

回答by Deele

TimDog answer was best solution.

TimDog 的回答是最好的解决方案。

In addition, just remember, transform string in this case means, that it will add 400 points to every path point/line X coordinate, and 0 points to every Y coordinate.

另外,请记住,在这种情况下,变换字符串意味着,它将为每个路径点/线的 X 坐标添加 400 个点,并为每个 Y 坐标添加 0 个点。

That means, M100 100L190 190will turn into M500 100L590 190.

这意味着,M100 100L190 190将变成M500 100L590 190

So, if you need to move a path element to another position, the difference between current position and new position coordinates should be calculated. You can use first element to do that:

因此,如果您需要将路径元素移动到另一个位置,则应计算当前位置与新位置坐标之间的差异。您可以使用第一个元素来做到这一点:

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

Hope this will help someone.

希望这会帮助某人。

回答by user56reinstatemonica8

Here's some code that generalises the best of the above answers and gives Raphael paths a simple .attr({pathXY: [newXPos, newYPos]})attribute similar to .attr({x: newXPosition})and .animate({x: newXPosition})for shapes.

下面是一些代码,可以推广的最好上述回答,并给出了拉斐尔路径的简单的.attr({pathXY: [newXPos, newYPos]})类似属性 .attr({x: newXPosition}).animate({x: newXPosition})用于形状。

This lets you move your path to a fixed, absolute positionor move it by a relative amountin a standard way without hardcoding path strings or custom calculations.

这使您可以将路径移动到固定的绝对位置或以标准方式将其移动相对量,而无需硬编码路径字符串或自定义计算。



Edit:Code below works in IE7 and IE8. An earlier version of this failed in IE8 / VML mode due to a Raphael bug that returns arrays to .attr('path') in SVG mode but strings to .attr('path') in VML mode.

编辑:下面的代码适用于 IE7 和 IE8。早期版本在 IE8/VML 模式下失败,这是由于Raphael 错误,它在 SVG 模式下将数组返回到 .attr('path') 而在 VML 模式下将字符串返回到 .attr('path')



Code

代码

Add this code (Raphael customAttribute, and helper function) after defining paper, use as below.

定义后添加此代码(Raphael customAttribute和辅助函数)paper,使用如下。

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


Usage

用法

For absolute translation (move tofixed X,Y position) - Live JSBIN demo

对于绝对平移(移动固定的 X、Y 位置) -现场 JSBIN 演示

Works with any path or set of paths including sets of sets (demo). Note that since Raphael sets are arrays not groups, it moves each item in the set to the defined position - not the centre of the set.

适用于任何路径或路径集,包括集(演示)。请注意,由于 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 needs to handle both x and y co-ordinates together in the same customAttribute so they can animate together and so they stay in sync with each other.

Raphael 需要在同一个 customAttribute 中同时处理 x 和 y 坐标,以便它们可以一起制作动画并保持彼此同步。

For relative translation (move by+/- X,Y) - Live JSBIN demo

对于相对翻译(+/- X,Y移动) -现场 JSBIN 演示

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

This also works with sets, but again don't forget that Raphael's sets aren't like groups - each object moves to one position relative to the average position of the set, so results may not be what are expected (example demo).

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



For animation (move a path to relative or absolute positions)

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

Before animating the first time, you need to set the pathXY values, due to a bug/missing feature up to Raphael 2.1.0 where all customAttributes need to be given a numeric value before they are animated (otherwise, they will turn every number into NaN and do nothing, failing silently with no errors, or not animating and jumping straight to the final position).

在第一次动画之前,您需要设置 pathXY 值,因为在 Raphael 2.1.0 之前的一个错误/缺失功能,所有 customAttributes 在动画之前都需要被赋予一个数值(否则,它们会将每个数字变成NaN 并且什么都不做,无声无息地失败,没有错误,或者没有动画并直接跳到最终位置)。

Before using .animate({pathXY: [newX,newY]});, run this helper function:

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

somePath.pathXY();

回答by Hiroshi Ichikawa

Yet another way is to use "transform" attribute:

另一种方法是使用“transform”属性:

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

to move the path to the right by 400px, relative to the original position.

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

This should work for all shapes, including paths and rectangles.

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

Note that:

注意:

  • "transform" attribute is independent of x, y, cx, cy, etc. So these attributes are not updated by the animation above.
  • The value of "transform" attribute is always based on the original position, not the current position. If you apply the animation below after the animation above, it will move it 800px to the left relatively, instead of moving it back to its original position.

    testpath.animate({transform: "t-400,0"}, 1000);
    
  • "transform" 属性独立于 x、y、cx、cy 等。因此这些属性不会被上面的动画更新。
  • “transform”属性的值总是基于原始位置,而不是当前位置。如果在上面的动画之后应用下面的动画,它将相对向左移动 800px,而不是将其移动回原来的位置。

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