Applying scaling and rotation on a view using CGAffineTransform

Alexandre picture Alexandre · Nov 9, 2011 · Viewed 20.3k times · Source

So I need to apply some scaling and some rotation to a view (I do this using gestures), so for each gesture I update the current scalling and rotation values with something like:

self.scaleWidth *= gesture.scale; //When I detect an horizontal pinch
self.scaleHeight *= gesture.scale; //When I detect a vertical pinch
self.rotationAngle += gesture.rotationAngle; //When I detect a rotation

Then I do the following to transform the view:

CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, self.scaleWidth, self.scaleHeight);
self.theSubViewToTransform.transform = CGAffineTransformRotate(transform, self.rotationAngle);

When I only do scaling, it works fine. When I do scaling then rotate, it rotates fine. When after rotating I try to scale again, it doesn't work fine: the scale is applied as if done after the rotation, deforming my image structure.

I thought I did what needed to be done to avoid this: starting each time from an identity transform, scaling first then rotating, but obviously I was wrong...

Does any one know what's wrong with my implementation ?

Thanks

Answer

RPeck picture RPeck · Nov 11, 2011

If you start with the identity transform every time, the end result you are setting the subview's transform to will only include the scaling and rotation from the current gesture. Instead of starting with the identity, start with the current transform of the view.

CGAffineTransform transform = self.theSubViewToTransform.transform;
transform = CGAffineTransformScale(transform, self.scaleWidth, self.scaleHeight);
transform = CGAffineTransformRotate(transform, self.rotationAngle);
self.theSubViewToTransform.transform = transform;

The first time this executes, the transform will start out as the identity transform. On subsequent executions, it will make the new changes on top of the old ones.