SVG动画沿着路径与拉斐尔

时间:2022-11-05 14:02:27

I have a rather interesting issue with SVG animation.

我对SVG动画有一个相当有趣的问题。

I am animating along a circular path using Raphael

我正在用Raphael做圆周运动。

obj = canvas.circle(x, y, size);
path = canvas.circlePath(x, y, radius);                
path = canvas.path(path); //generate path from path value string
obj.animateAlong(path, rate, false);

The circlePath method is one I have created myself to generate the circle path in SVG path notation:

圆环路径方法是我自己创建的一种方法,用于生成SVG路径表示法中的圆形路径:

Raphael.fn.circlePath = function(x , y, r) {      
  var s = "M" + x + "," + (y-r) + "A"+r+","+r+",0,1,1,"+(x-0.1)+","+(y-r)+" z";   
  return s; 
} 

So far, so good - everything works. I have my object (obj) animating along the circular path.

到目前为止,一切都很好。我让对象(obj)沿着圆形路径动画。

BUT:

但是:

The animation only works if I create the object at the same X, Y coords as the path itself.

只有当我在路径本身的X, Y上创建对象时,动画才会工作。

If I start the animation from any other coordinates (say, half-way along the path) the object animates in a circle of the correct radius, however it starts the animation from the object X,Y coordinates, rather than along the path as it is displayed visually.

如果我从任何其他坐标开始动画(比如,沿着路径的一半),那么对象就会在正确的半径范围内动画,但是它会从对象X,Y坐标开始动画,而不是沿着它所显示的路径。

Ideally I would like to be able to stop/start the animation - the same problem occurs on restart. When I stop then restart the animation, it animates in a circle starting from the stopped X,Y.

理想情况下,我希望能够停止/启动动画——重启时也会出现同样的问题。当我停止,然后重新启动动画,它在一个圆圈中动画,从停止的X,Y开始。

UPDATE

更新

I created a page that demonstrates the issue: http://infinity.heroku.com/star_systems/48eff2552eeec9fe56cb9420a2e0fc9a1d3d73fb/demo

我创建了一个页面来演示这个问题:http://infinity.heroku.com/star_systems/48eff2552eeec9fe56cb9420a2e0fc9a1d3d73fb/demo

Click "start" to start the animation. When you stop and re-start the animation, it continues from the current circle coords in a circle of the correct dimensions.

点击“开始”启动动画。当您停止并重新启动动画时,它将继续从当前的圆形坐标转换到正确的维度。

1 个解决方案

#1


6  

The problem is that Raphael has no way of knowing that the circle is already part-way along the path. The "start" function means just that -- start an animation. imo it would be broken if it did anything else.

问题是拉斐尔无法知道这个圆已经沿着这条路走了一半。“开始”函数的意思是——开始一个动画。在我看来,如果它做了别的事情,它就会被打破。

That said, your use case is a valid one, and might warrant another function -- a 'pause' of some sort. Of course, getting that into trunk would take longer probably than you want to wait.

也就是说,您的用例是一个有效的用例,可能需要另一个函数——某种“暂停”。当然,将它放入trunk可能需要比您希望等待的时间更长。

From the Raphael source code, here's what happens when you call 'stop'.

从Raphael的源代码中,我们来看看当你调用“stop”时会发生什么。

Element[proto].stop = function () {
    animationElements[this.id] && animationElements[length]--;
    delete animationElements[this.id];
    return this;
};

This decrements the total number of animations, and removes that animation from the list. Here's what the 'pause' function might look like:

这将减少动画的总数,并从列表中删除该动画。“暂停”函数是这样的:

Element[proto].pause = function () {
    animationElements[this.id] && animationElements[length]--;
    this._paused_anim = animationElements[this.id];
    delete animationElements[this.id];
    return this;
};

this saves the animation to be resumed later. then

这将保存稍后要恢复的动画。然后

Element[proto].unpause = function () {
    this._paused_anim && (animationElements[this.id]=this._paused_anim);
    ++animationElements[length] == 1 && animation();
    return this;
};

would unpause. Given scoping conditions, these two functions might need to be injected right into the Raphael source code (it's core hacking, I know but sometimes there's no alternative). I would put it right below the "stop" function shown above.

将unpause。给定范围条件,这两个函数可能需要直接注入到Raphael源代码中(我知道这是核心攻击,但有时别无选择)。我把它放在上面显示的“停止”函数下面。

Try that, and tell me how it goes.

试试,告诉我怎么回事。

====EDIT====

= = = = = = = =进行编辑

Ok, so it looks like you'll have to modify the "start" attribute of animationElements[this.id]... something like:

看来你得修改animationElements[this.id]的"start"属性……喜欢的东西:

this._pause_time = (+new Date) - animationElements[this.id].start;

in the pause, and then

在停顿中,然后

animationElements[this.id].start = (+new Date) - this._pause_time;

on resume.

在简历上。

http://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js#L3064

http://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js L3064

#1


6  

The problem is that Raphael has no way of knowing that the circle is already part-way along the path. The "start" function means just that -- start an animation. imo it would be broken if it did anything else.

问题是拉斐尔无法知道这个圆已经沿着这条路走了一半。“开始”函数的意思是——开始一个动画。在我看来,如果它做了别的事情,它就会被打破。

That said, your use case is a valid one, and might warrant another function -- a 'pause' of some sort. Of course, getting that into trunk would take longer probably than you want to wait.

也就是说,您的用例是一个有效的用例,可能需要另一个函数——某种“暂停”。当然,将它放入trunk可能需要比您希望等待的时间更长。

From the Raphael source code, here's what happens when you call 'stop'.

从Raphael的源代码中,我们来看看当你调用“stop”时会发生什么。

Element[proto].stop = function () {
    animationElements[this.id] && animationElements[length]--;
    delete animationElements[this.id];
    return this;
};

This decrements the total number of animations, and removes that animation from the list. Here's what the 'pause' function might look like:

这将减少动画的总数,并从列表中删除该动画。“暂停”函数是这样的:

Element[proto].pause = function () {
    animationElements[this.id] && animationElements[length]--;
    this._paused_anim = animationElements[this.id];
    delete animationElements[this.id];
    return this;
};

this saves the animation to be resumed later. then

这将保存稍后要恢复的动画。然后

Element[proto].unpause = function () {
    this._paused_anim && (animationElements[this.id]=this._paused_anim);
    ++animationElements[length] == 1 && animation();
    return this;
};

would unpause. Given scoping conditions, these two functions might need to be injected right into the Raphael source code (it's core hacking, I know but sometimes there's no alternative). I would put it right below the "stop" function shown above.

将unpause。给定范围条件,这两个函数可能需要直接注入到Raphael源代码中(我知道这是核心攻击,但有时别无选择)。我把它放在上面显示的“停止”函数下面。

Try that, and tell me how it goes.

试试,告诉我怎么回事。

====EDIT====

= = = = = = = =进行编辑

Ok, so it looks like you'll have to modify the "start" attribute of animationElements[this.id]... something like:

看来你得修改animationElements[this.id]的"start"属性……喜欢的东西:

this._pause_time = (+new Date) - animationElements[this.id].start;

in the pause, and then

在停顿中,然后

animationElements[this.id].start = (+new Date) - this._pause_time;

on resume.

在简历上。

http://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js#L3064

http://github.com/DmitryBaranovskiy/raphael/blob/master/raphael.js L3064