Reputation: 3186
I have created a small demo in this codepen.
When clicking any of the four buttons, the object is rotated to the correct position using the following...
function rotateTo(angle) {
var ring = paper.select("#INNER_RING");
var bbox = ring.getBBox();
var cx = bbox.cx;
var cy = bbox.cy;
var trans = 'r' + angle + ' ' + cx + ' ' + cy; // + 's1,1,' + cx + ',' + cy;
console.log(trans);
ring.stop().animate({
transform: trans
},
750,
mina.linear,
function() {
settings.currentRotation = angle;
});
}
On the first rotation, everything goes great. However, subsequent rotations not only rotate but appear to scale as the rotation takes place. The object does end up in the correct final position, but the scaling is not wanted.
What could be happening as part of the first transformation that would cause subsequent ones to do this?
Upvotes: 0
Views: 210
Reputation: 13842
Animating matrices from a previous matrix typically gets pretty messy, as they often don't do things that we think they do (I asked a previous similar question in the past here which may be of use, getting your head around matrix animation if you wanted a deeper understanding). At the start of the first animation, there is no transform matrix to animate from, so it's all pretty straightforward.
However, at the end of the 1st animation, there is a transform matrix left there applying to the element, which causes a problem, as the next animation it tries to animate from that last matrix.
It isn't quite clear what you actually want to do, on a subsequent button press. Whether you want to rotate 'another' 90 degrees, or just rotate 90 from scratch again.
If you just want to repeat the animation, you could just reset the transform to scratch, which simply gets around the problem (but note, there may be an issue if you press the button mid animate).
ring.attr('transform','')
If you want to do more complex things, and need to animate from a previous state, I would use a slightly different method of animate, and not animate on an element, but use Snap.animate and build your transform string each time. So the could could look more like this...
var rotateFrom = settings.currentRotation;
var rotateTo = rotateFrom + parseInt(angle)
Snap.animate(rotateFrom, rotateTo, function( val ) {
ring.transform( 'r' + val + ',' + cx + ',' + cy )
}, 750, mina.linear, function() {
settings.currentRotation = rotateTo;
});
Snap.animate() takes 2 initial arguments that are a starting value and an end value, and then interpolates between them, passing that as 'val' to the function which is passed in. The docs for that can be found here
This way, you don't care about animating from previous transforms (which are stored as matrices), and you control the real specifics of whats happening each animation loop.
You may just need to tweak it and store the rotation each time the func is called (rather than just when it finishes), depending on what you want to do mid-animation if the button is pressed before it's finished.
Upvotes: 1