How to Use Cgaffinetransformmakerotation

How to use CGAffineTransformMakeRotation?

CGAffineTransformMakeRotation expects angle in radians, not in degrees.

#define DEGREES_TO_RADIANS(x) (M_PI * (x) / 180.0)
...

CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));

CGAffineTransformMakeRotation with negative M_PI

As I stated in my first comment and as Segii already wrote: the animation will take the shortest distance between where it's value is at now and where it is trying to go. The best solution imho is to use CABasicAnimation for forcing a counterclockwise rotation:

let anim = CABasicAnimation(keyPath: "transform.rotation")
anim.fromValue = M_PI
anim.toValue = 0
anim.additive = true
anim.duration = 2.0

myView.layer.addAnimation(anim, forKey: "rotate")
myView.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI))

This will rotate it by 180 counter clockwise in one go.

The angle you specify in the last line + the fromValue is the starting angle -> 0. And then the rotation will go the distance (toValue - fromValue) = 0 - M_PI = - M_PI -> counter clockwise 180 degree rotation.

Can I use CGAffineTransformMakeRotation to rotate a view more than 360 degrees?

You can rotate a view, by some number of radians, regardless of whether it is less than a full rotation or many multiples of a full rotation, without having to split the rotation into pieces. As an example, the following code will spin a view, once per second, for a specified number of seconds. You can easily modify it to spin a view by a certain number of rotations, or by some number of radians.

- (void) runSpinAnimationWithDuration:(CGFloat) duration;
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

[myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

How to use CGAffineTransformMakeRotation for NSString

CGAffineTransformMakeRotation is used to set the transform property of a UIView, NSString is not a UIView so it cant be transformed, it has not concept of rotation

you need to do this at display time with a UILabel

an example:

NSString *myString = @"whatever";
CGAffineTransform stringTransform = CGAffineTransformMakeRotation(M_PI / 2.0f);

UILabel *stringLabel = [[UILabel alloc] initWithFrame:labelFrame];
stringLabel.transform = stringTransform;
stringLabel.text = myString;

[self.view addSubview:stringLabel];

About CGAffineTransformMakeRotation rotation direction?

This is an error in documentation.

Here they describe matrix and provide equations which they use to do the transform:

Sample Image

If you do the math, you'll see that for positive angles, it gives rotation counterclockwise when Y axis direction is upwards as in OS X and clockwise when Y axis directed downwards as in iOS

For example you may try to transform point (5,0) with 90 degrees, you will get (0,5), which means clockwise for iOS and counterclockwise for OS X.

The same piece of documentation still have the (false) part you quoted:

In iOS, a positive value specifies counterclockwise
rotation and a negative value specifies clockwise rotation. In OS X, a
positive value specifies clockwise rotation and a negative value
specifies counterclockwise rotation.

Which is clearly wrong, because the equations (which are the part of the same document and are pretty standard rotation equations) say the opposite.

objective c: CGAffineTransformMakeRotation

Instead of trying to have two UIView animations together to create one visual animation, you could just use Core Animation and do it all in one animation. Using Core Animation you can tell the animation to automatically reverse (go to 45 degrees during 1.5 seconds and then back again during the same duration) and you won't have to care about timing the two animations together. You could do it like this:

CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
[rotate setFromValue:[NSNumber numberWithFloat:0.0]];
[rotate setToValue:[NSNumber numberWithFloat:degreesToRadians(45)]];
[rotate setDuration:1.5];
[rotate setAutoreverses:YES]; // go back the same way
[rotate setTimingFunction:[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]];

[[myDial layer] addAnimation:rotate forKey:@"dangleMyDial"];

If you haven't imported QuartzCore.framework into your project and imported the , you'll need to do so for Core Animation to work.

Rotate an UIView with CGAffineTransformMakeRotation

When you add the transform to myView you are not applying a transform to it's existing transformed state, but rather overwriting the transform. This means that when you set transform = CGAffineTransformMakeRotation(M_PI/2) for the second time, you are not actually changing the transform at all.

EDIT:
As Rob pointed out, there is no need to use the property rotationInRadians when the rotation value is already stored in the transform. Instead you can simply modify the existing transform like this:

[UIView animateWithDuration:0.2 animations:^{
_myView.transform = CGAffineTransformRotate(_myView.transform, M_PI/2);
}];

Below is the not ideal solution that I previously presented.

You will need a variable that keeps track of your rotation. You will increment this variable by your desired amount each time you want to rotate, then create a new transform based on the new value of the variable.

Make a property to do this:

@property (nonatomic, assign) CGFloat rotationInRadians;

Initialize it to 0 in your init method. Then modify your rotateView method to increment rotationInRadians and apply the new transform.

- (IBAction)rotateView:(id)sender {
self.rotationInRadians += M_PI/2;
[UIView animateWithDuration:0.2 animations:^{
_myView.transform = CGAffineTransformMakeRotation(self.rotationInRadians);
}];
}

Using cgaffinetransformmakescale and cgaffinetransformmakerotation deforms my view

The problem is animating a combined scaling and rotation. The end result is the same as animating them separately, but the frames in between are not easily defined. So the animation framework makes a guess, and it is not what you are expecting.

If you want the animation to show a rotation and scaling separately, you need to apply them separately to the view hierarchy. For example:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
view.backgroundColor = [UIColor greenColor];
[self.view addSubview:view];
self.someView = view;

UIView *innerView = [[UIView alloc] initWithFrame:view.bounds];
innerView.backgroundColor = [UIColor blueColor];
[view addSubview:innerView];
self.someInnerView = innerView;

The animation splits the transform:

[UIView animateWithDuration:10
delay:1
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.someView.center = CGPointMake(CGRectGetWidth(self.view.bounds) - CGRectGetWidth(self.someView.frame) / 2, 150);

self.someView.transform = CGAffineTransformMakeRotation(M_PI);
self.someInnerView.transform = CGAffineTransformMakeScale(2, 0.5);

}
completion:^(BOOL finished) {

}];

Using CGAffineTransformMakeRotation to rotate a point

CGPointApplyAffineTransform returns the transformed point. It doesn't mutate the CGPoint you pass in.

CGPoint transformedPoint = CGPointApplyAffineTransform(positionToRotate, affine);


Related Topics



Leave a reply



Submit