Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying scaling and rotation on a view using CGAffineTransform

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

like image 704
Alexandre Avatar asked Nov 09 '11 11:11

Alexandre


People also ask

What is CGAffineTransform in Swift?

The CGAffineTransform type provides functions for creating, concatenating, and applying affine transformations. Affine transforms are represented by a 3 by 3 matrix: Because the third column is always (0,0,1) , the CGAffineTransform data structure contains values for only the first two columns.

How do you rotate a view in Swift?

rorateview.swiftlet bitmap: CGContext = UIGraphicsGetCurrentContext()! //Move the origin to the middle of the image so we will rotate and scale around the center. let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!


1 Answers

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.

like image 147
RPeck Avatar answered Nov 07 '22 12:11

RPeck