Reputation:
The object could be simple, a rect or circle. But the path should be a bezier curve. Please provide javascript/Raphael code if not too much trouble.
It will be nice if there is trailing effect of the moving object during annimation.
Upvotes: 9
Views: 14488
Reputation: 61259
There's a nice solution here.
I've copied the code below:
/*
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);
});
};
Upvotes: 2
Reputation: 1314
Just in case you are trying to use this with RaphaelJS 2 (animateAlong doesn't exist anymore), here you can see a possible solution: http://jsfiddle.net/gyeSf/17/.
And here the original discussion: https://groups.google.com/forum/#!searchin/raphaeljs/animatealong/raphaeljs/W9bA0SkArVY/KnPRKi8uFrsJ
Edit: And here another example: http://raphaeljs.com/gear.html
Upvotes: 12
Reputation: 57685
Just use the .animateAlong()
method.
It takes 4 arguments:
Essentially from the documentation:
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});
});
});
};
Upvotes: 2
Reputation: 1431
It seems that you cant do that using Raphaёl animate()
method (since it changes object attributes linearly).
I would offer you to implement a function that changes object position each millisecond or so according to Bézier curve formula. Use Raphaёl translate()
method and JavaScript timers.
Upvotes: 1