Quang Anh Chu Quang Anh Chu - 4 months ago 54
Javascript Question

Multistage of svg transform animation with Snap SVG

I'm building a small UI which provides users progress of downloading or loading certain information. Here is the codes so far

http://jsfiddle.net/pge1wukj/4/

var s = Snap("svg");
var movepath = s.select("#movePath").attr({
"fill":"none"
});
var dapath = s.select("#dapath").attr({
stroke: "#cdcdcd",
"stroke-width": 5,
});
var dapoints = [242,334.5, 372,334.5, 372,390, 320.5,390.5 ,308.5,421.5 ,293.5,391.5 ,242,391]
var circle = s.select("circle");
var poly = s.select("polygon");

$("a").click(function(){
circle.animate({
opacity: 0
},100);
poly.polyAnimate(dapoints,100,mina.linear,function(){
moveAlongPath(poly,{x:308,y:421},s.halfArc(308,421,135,382,50,0),100);
});
dapath.animate({
d:"M135,382.5c0,52.159,85,79.031,170.001,79.498 C 390.3,462.466,475.598,436.344,475,382.5",
},100,function(){
dapath.animate({d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},100,function(){
dapath.animate({
d:"M135,382.292c0,0,85.999-22.759,171-22.292c85.299,0.468,169,22.292,169,22.292"
},100,function(){
dapath.animate({
d:"M136,382.415c0,0,90.999,13.118,176,13.585c85.299,0.468,164-13.585,164-13.585"
},100,function(){
dapath.animate({
d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},500,mina.bounce,function(){
var pathclone = dapath.clone().attr({
stroke: "blue",
strokeDashoffset: 500,
strokeDasharray: 500
});
var datext = s.text(100,330,"90").attr("style","text-align: center");
var banner = s.group(poly,datext);
moveAlongPath(banner,{x:136,y:382.415},movepath,3600);
var tick = 0;
var interval = setInterval(function(){
tick += 1;
var red = Math.random()*255;
var blue = Math.random()*255;
var green = Math.random()*255;
var hex = Snap.rgb(red,green,blue);
var dadatext = $("text").text(tick+" %")
if(tick % 10 == 0){
dadatext.attr({"font-size":"30px","fill":hex});
};
if (tick >= 100){clearTimeout(interval)};
},36);
pathclone.animate({
"stroke-dashoffset":0,
},5300);
var paths = Snap.set().push(dapath,pathclone);
paths.animate({
d:"M135,382.5c0,0,30,17,42,17c10,0.208,298-17,298-17"
},300,function(){
paths.animate({
d:"M135,382.5c0,0,287,17.208,297,17c12,0,43-17,43-17"
},2900,function(){
paths.animate({d:"M135,382.5c0,0,287,17.208,297,17c12,0,43-17,43-17"},100,function(){
paths.animate({
d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},200,function(){
$("a").off("click");
/* End of animation */
/* Ready for next transformation*/
banner.animate({
transform: "rotate(180deg)"
},200);
})
})
});
})

});
});
})
})
});
});`


At the end of the animation, the banner should rotate 180 deg on the sharp point. However it doesn't animate as i expected. Is there any solution to this ? transforming animation is intimidating and i don't fully understand it....

Ian Ian
Answer

I think what you are missing is that you need to provide the original transform to include, otherwise it will assume you are just replacing that transform.

So with this line...

banner.animate({ transform: 'rotate(180)' },200);

What this really means is, I'm going to overwrite any current transforms and animate to a new one of rotate(180).

What you probably want is...keep any existing transforms, and now rotate(180) as well.

So you probably want something more like this...transform() with no parameters will give us the existing transform. So we can combine.

transform -> existingtransform then apply additional transform

This would look like the following.

banner.animate({ transform: banner.transform() + " s-1,1" },200);

I'm not quite sure of the rotation effect you are after (did you mean it to go upside down or back to front?), but 's-1,1' may have been what you were thinking of.

jsfiddle example

Edit: jsfiddle with alternate rotation. Note, for this, you need to take into account 'where' the polygon is, in relation to the group, as its offset as you have moved it (and then also moved the group).

Edit: The rotation center point is quite difficult, as we have the polygon points offset (not centred around 0) and then translated. Also the group they are in is translated, so you've kinda of got 3 things going on.

To try and help understand getting the actual points, I have rewritten the rotation animation.

banner.animate({ transform: banner.transform() + "r180," + banner.getBBox(1).cx + ',' + banner.getBBox(1).y2 },200);

We get the bounding box, which calculates the centre for us. The pivot point is mid length cx, and the lowest y point is y2. I suspect there is an easier way to get the whole thing working to reduce the transform complexity in the overall code, but there's a bit too much to break down for a question here.

jsfiddle with getBBox