SVG анимация по пути с Рафаэлем - PullRequest
10 голосов
/ 13 апреля 2010

У меня довольно интересная проблема с SVG-анимацией.

Я оживляю по кругу, используя Рафаэля

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

Метод circlePath - это метод, который я создал сам для генерации траектории круга в нотации 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; 
} 

Пока все хорошо - все работает. У меня есть объект (объект), анимирующийся по круговому пути.

НО:

Анимация работает только в том случае, если я создаю объект с такими же координатами X, Y, что и сам путь.

Если я запускаю анимацию с любых других координат (скажем, на полпути вдоль пути), объект анимируется по кругу правильного радиуса, однако он начинает анимацию с координат X, Y объекта, а не вдоль путь, как он отображается визуально.

В идеале я хотел бы иметь возможность остановить / запустить анимацию - та же проблема возникает при перезапуске. Когда я останавливаюсь, затем перезапускаю анимацию, она оживляет по кругу, начиная с остановленных X, Y.

UPDATE

Я создал страницу, демонстрирующую проблему: http://infinity.heroku.com/star_systems/48eff2552eeec9fe56cb9420a2e0fc9a1d3d73fb/demo

Нажмите «Пуск», чтобы запустить анимацию. Когда вы останавливаете и перезапускаете анимацию, она продолжается от текущих координат круга в круг правильных размеров.

1 Ответ

6 голосов
/ 18 апреля 2010

Проблема в том, что у Рафаэля нет возможности узнать, что круг уже на полпути вдоль пути. Функция «старт» означает только это - запустить анимацию. ИМХО он будет сломан, если он сделает что-нибудь еще.

Тем не менее, ваш вариант использования является допустимым и может потребовать другую функцию - некоторую «паузу». Конечно, получение этого в багажник займет больше времени, чем вы хотите.

Из исходного кода Рафаэля , вот что происходит, когда вы называете «стоп».

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

Это уменьшает общее количество анимаций и удаляет эту анимацию из списка. Вот как может выглядеть функция pause:

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

это сохраняет анимацию для возобновления позже. то

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

сделает паузу. Учитывая условия области видимости, эти две функции, возможно, должны быть внедрены прямо в исходный код Raphael (это ядро ​​взлома, я знаю, но иногда нет альтернативы). Я бы поставил его прямо под функцией «стоп», показанной выше.

Попробуй это, и скажи мне, как это происходит.

==== EDIT ====

Хорошо, похоже, вам нужно изменить атрибут "start" animationElements [this.id] ... что-то вроде:

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

в паузе, а затем

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

на резюме.

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

...