I made some good progress last night making animate-frames more raphaël.js-like. Before I push those changes back into the main repository, I would like to explore easing in the
animate()
method.Ultimately, the
animate()
method in animate-frames is calling the translate_object()
method, which animates movement with animateAlong()
:translate_object: function(frame, x, y, ms, easing) {My first instinct is to add and
// offset between end coordinates and current location
var x_diff = x - frame[frame.length-1].getBBox().x;
var y_diff = y - frame[frame.length-1].getBBox().y;
for (var i=0; i<frame.length; i++) {
var obj = frame[i];
// calculate path starting from absolute coordinates and moving
// relatively from there by the offset
var p = "M " + obj.getBBox().x + " " + obj.getBBox().y +
" l " + x_diff + " " + y_diff;
// animate along that path
if (ms && ms > 50)
obj.animateAlong(p, ms);
else
obj.translate(x_diff, y_diff);
};
}
easing
parameter to animateAlong()
. Sadly, according to the documentation (and the code), the method signature only takes path
, ms
, rotate
, and callback
(invoked after the animation completes).Dang.
So maybe I can use
animate()
instead of animateAlong()
:// animate along that pathBut when I do that, my players don't move at all. Grr.. what gives?
if (ms && ms > 50)
obj.animate({x: x + x_diff, y: y + y_diff}, ms, easing);
// ...
To find out, I break the problem down to basics. Using a raphaël paper object,
r
, I create a circle and animate its center x-coordinate:c = r.circle(200, 200, 10).attr({stroke: "#333", "stroke-width": 4, "fill": '#333'})That works. The circle moves from 200, 200 to 0, 200 over the course of 5 seconds.
c.animate({cx: 0}, 5000)
Next I try drawing an object with SVG path information—the same way that the objects inside my animations are being drawn:
o = r.path("m 27.970621,11.503807 c 0.09878,4.794487 -3.625825,9.254299 -8.244694,9.888541 C 15.282994,22.185422 10.583894,19.322284 9.1090954,14.943452 7.4780985,10.605964 9.2934491,5.2861677 13.201573,2.948285 c 3.892493,-2.53638571 9.452051,-1.6375587 12.397375,2.008774 1.523084,1.7954543 2.381825,4.1636216 2.371673,6.546748 z").attr({fill: '#090'})That does not work. The player stays at its original coordinates.
o.animate({cx: 50}, 5000)
I can animate certain other attributes, such as the fill color:
o.animate({fill: '#00f'}, 5000)From this, I conclude that it is not possible to animate location elements on objects drawn via paths. That is not too surprising based on my earlier investigation. Not surprising, but still disappointing.
I am not quite ready to abandon easing. I really want to use it to animate collisions (the "bounce" easing is particularly nice). Since I cannot animate-with-easing the SVG paths that make up my frames, I think that I ought to be able to hide the frames, show another object that can be animated. That is not perfect, but it ought to suffice for my purposes.
I will get started on that tomorrow.
Day #240
you can animate the path objects by giving another path as a parameter to the animate function
ReplyDeleteThe particular use-case that I am trying to solve here is to animate paths *and* translate them at the same time:
ReplyDeletehttp://eee-c.github.com/raphael-animate-frames/demo.html
AFAIK that's not possible: http://japhr.blogspot.com/2010/07/combining-raphaeljs-animations.html
Happy to be proven wrong though :)
If you want to animate a path using "translate" - why don't you simply clone the path, translate the clone and then animate the path attribute...
ReplyDeletehttp://jsfiddle.net/digiguru/pBCwy/
var paper = Raphael("board", 900, 900);
var graphic = paper.path("M 0 0 L 20 0 L 10 20 z");
tempGraphic = graphic.clone();
tempGraphic.translate(30,80);
graphic.animate({path:this.tempGraphic.attr("path")}, 500);
tempGraphic.remove();
Or even easier, animate using the "translation" attribute.
ReplyDeletehttp://jsfiddle.net/digiguru/pBCwy/1/
var paper = Raphael("board", 900, 900);
var graphic = paper.path("M 0 0 L 20 0 L 10 20 z");
graphic.animate({translation: '40 80'}, 2000);