Как анимировать объект Рафаэля вдоль пути?

Объект может быть простым, прямоугольником или кругом. Но путь должен быть кривой Безье. Если не сложно, предоставьте код javascript/Raphael.

Было бы неплохо, если бы во время анимации был эффект трейлинга движущегося объекта.


person Community    schedule 23.06.2009    source источник
comment
Этот вопрос пахнет "сделай за меня домашнее задание"   -  person Adriano Varoli Piazza    schedule 23.06.2009
comment
Погуглите, прежде чем задавать вопрос   -  person joe    schedule 23.06.2009
comment
Хорошо опубликовать то, что вы пробовали, прежде чем публиковать в стеке, чтобы люди знали, что вы не просто просите их сделать вашу работу за вас.   -  person mheavers    schedule 03.11.2011


Ответы (4)


На всякий случай, если вы пытаетесь использовать это с RaphaelJS 2 (animateAlong больше не существует), здесь вы можете увидеть возможное решение: http://jsfiddle.net/gyeSf/17/.

А вот исходное обсуждение: https://groups.google.com/forum/#!searchin/raphaeljs/animatealong/raphaeljs/W9bA0SkArVY/KnPRKi8uFrsJ

Изменить: А вот еще один пример: http://raphaeljs.com/gear.html

person José M. Gilgado    schedule 11.02.2012
comment
вы проходите красную точку правильно, можно ли передать изображение по этому пути? - person Ajax3.14; 28.06.2013

Просто используйте метод .animateAlong().

Он принимает 4 аргумента:

  1. path - объект или строка, элемент пути или строка пути, по которой будет анимироваться элемент
  2. мс — число — продолжительность анимации, указанная в миллисекундах.
  3. rotate - логическое значение - [необязательно] если true, элемент будет вращаться по пути
  4. обратный вызов – функция – [необязательно]

По сути из документации:

window.onload = function() {
    var r = Raphael("canvas", 200, 200), 
        p = r.path("M10,50C10,100,90,0,90,50C90,100,10,0,10,50Z")
             .attr({stroke: "#ddd"}),
        e = r.ellipse(10, 50, 4, 4).attr({stroke: "none", fill: "#f00"});
    r.rect(0, 0, 200, 200).attr({stroke: "none", fill: "#000", opacity: 0})
     .click(function () {
         e.attr({rx: 5, ry: 3})
          .animateAlong(p, 4000, true, function () {        // Animate along path
              e.attr({rx: 4, ry: 4});
          });
     });
}​;

Попробуйте этот jsFiddle (нажмите, чтобы активировать)

person Peter Ajtai    schedule 13.10.2010
comment
Метод animateAnong недоступен в новой версии rapheljs - person Laxmikant Dange; 20.05.2014

Хорошее решение есть здесь.

Я скопировал код ниже:

/*

You can copy and paste the below into your codebase somewhere.
As long as Raphael is a global object, it'll just work.

USAGE (same default values for optional parameters as Raphaël's "animate" method)
=====
element.animateAlong({
    path: REQUIRED - Path data string or path element,
    rotate: OPTIONAL - Boolean whether to rotate element with the direction it is moving
                       (this is a beta feature - currently kills existing transformations
                        and rotation may not be perfect),
    duration: OPTIONAL - Number in milliseconds,
    easing: OPTIONAL - String (see Raphaël's docs),
    debug: OPTIONAL - Boolean, when set to true, paints the animating path, which is
                      helpful if it isn't already rendered to the screen
},
props - Object literal containing other properties to animate,
callback - Function where the "this" object refers to the element itself
);

EXAMPLE
=======
var rect = paper.rect(0,0,50,50);
rect.animateAlong({
    path: "M0,0L100,100",
    rotate: true,
    duration: 5000,
    easing: 'ease-out',
    debug: true
},
{
    transform: 's0.25',
    opacity: 0
},
function() {
    alert("Our opacity is now:" + this.attr('opacity'));
});

*/

Raphael.el.animateAlong = function(params, props, callback) {
    var element = this,
        paper = element.paper,
        path = params.path,
        rotate = params.rotate,
        duration = params.duration,
        easing = params.easing,
        debug = params.debug,
        isElem = typeof path !== 'string';

    element.path = 
        isElem
            ? path
            : paper.path(path);
    element.pathLen = element.path.getTotalLength();
    element.rotateWith = rotate;

    element.path.attr({
        stroke: debug ? 'red' : isElem ? path.attr('stroke') : 'rgba(0,0,0,0)',
        'stroke-width': debug ? 2 : isElem ? path.attr('stroke-width') : 0
    });

    paper.customAttributes.along = function(v) {
        var point = this.path.getPointAtLength(v * this.pathLen),
            attrs = {
                x: point.x,
                y: point.y 
            };
        this.rotateWith && (attrs.transform = 'r'+point.alpha);
        // TODO: rotate along a path while also not messing
        //       up existing transformations

        return attrs;
    };

    if(props instanceof Function) {
        callback = props;
        props = null;
    }
    if(!props) {
        props = {
            along: 1
        };
    } else {
        props.along = 1;    
    }

    var startAlong = element.attr('along') || 0;

    element.attr({along: startAlong}).animate(props, duration, easing, function() {
        !isElem && element.path.remove();

        callback && callback.call(element);
    });
};
person Richard    schedule 24.05.2012

Кажется, что вы не можете сделать это с помощью метода Рафаэля animate() (поскольку он линейно изменяет атрибуты объекта).

Я бы предложил вам реализовать функцию, которая меняет положение объекта каждую миллисекунду или около того в соответствии с формулой кривой Безье. Используйте метод Рафаэля translate() и таймеры JavaScript.

person aztek    schedule 23.06.2009