I have an image grid that I am zooming in and zooming out on click of the image. All is working fine, but I am having trouble controlling the rotation of the CGAffineTransform. I thought I could pass in the angle to control how my rotation is determined, but when I do so, the transform will not zoom in and I am left zoomed out.
I feel that I have missed the proper implementation of this along somewhere during creating my routine, so if anyone can point out where I went wrong I would appreciate it
Here is my code
float angle = -1.661799;
if(status == 0){
[UIView animateWithDuration:1.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGAffineTransform totalTransform =
CGAffineTransformMakeTranslation(-middleX , -middleY );
totalTransform = CGAffineTransformScale(totalTransform, 3.5f, 3.5f);
totalTransform = CGAffineTransformTranslate(totalTransform, middleX , middleY );
//totalTransform = CGAffineTransformMakeRotation(angle);
[self.view setTransform:totalTransform];
}completion:^(BOOL finished) {
}];
status++;
}else{
[UIView animateWithDuration:1.3f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGAffineTransform tr = CGAffineTransformMakeScale(1.00 ,1.00);
[self.view setTransform:tr];
}completion:^(BOOL finished) {
[UIView animateWithDuration:1.3f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGAffineTransform totalTransform =
CGAffineTransformMakeTranslation(-middleX , -middleY );
totalTransform = CGAffineTransformScale(totalTransform, 3.5f, 3.5f);
totalTransform = CGAffineTransformTranslate(totalTransform, middleX , middleY );
//totalTransform = CGAffineTransformMakeRotation(angle);
[self.view setTransform:totalTransform];
}completion:^(BOOL finished) {}];
}];
status = 0;
}
This is an old question--but in case anyone comes back to it:
When you are doing a series of transforms, you need to use the right call. There are two calls for each type of transform (rotate, translate, scale). One is used for combinations of transforms, and the other is for making a new transform.
The first call can be a "Make" call. The subsequent calls need to be the non-make variety.
"Make" call, which generates a transformation matrix:
CGAffineTransformMakeRotation(angle)
non-make call, which modifies an existing transformation matrix:
CGAffineTransformRotate(existingMatrix, angle)
so, from your code:
CGAffineTransform totalTransform =
CGAffineTransformMakeTranslation(-middleX , -middleY );
totalTransform = CGAffineTransformScale(totalTransform, 3.5f, 3.5f);
totalTransform = CGAffineTransformTranslate(totalTransform, middleX , middleY );
totalTransform = CGAffineTransformMakeRotation(angle);
Your first call created a matrix, as is appropriate. However your rotation call (the 4th call) should be:
totalTransform = CGAffineTransformRotate(totalTransform, angle);
Otherwise, as you noticed, you discard all the transformations before that call, and only get rotation, in this case, or whatever your last transformation would be.
Related
i had tried various method and couldn't figure out how to achieve this.i searched on internet a lot but can't figure out.
i have an ImageView (a wheel which spins) , i want to rotate it by 360 degree for 10 times(this is to just give user feel of fast turning wheel) , and then i want to rotate it by particular value say 90 degree( but it might be varying).
after this animation finishes i want to bring ImageView back to the initial position.
how do i achieve this ?
Thanks in advance.
well i found out how to do this.
i used below method to rotate by 360 degree for 10 times , and then rotate by particular degree.
-(void)rotate:(int)degreeToRotate
{
CGFloat radians = (M_PI/180) * degreeToRotate;
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations: ^{
//configuring to rotate 360 degree 10 times
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 10;
[_scoreImageView.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
} completion:^(BOOL finished) {
//rotate by particular degree
[ UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// -radians, to ensure clockwise rotation
self.scoreImageView.transform = CGAffineTransformMakeRotation(-radians);
} completion:^(BOOL finished) {
//method call to reset image original position
[self performSelector:#selector(resetPosition) withObject:nil afterDelay:3];
}];
}];
}
below method is used to reset image to original position.
-(void)resetPosition
{
[UIView animateWithDuration:0.2 animations:^() {
self.scoreImageView.transform = CGAffineTransformIdentity;
}];
}
I'm now implementing an app, for iOS devices so in objective C, and i was asking how to keep back to origin position an UIImageView after a rotation ?
For example, i use my UIImageView like this :
CGAffineTransform initialPosition = CGAffineTransformMakeRotation(0);
CGAffineTransform finalPosition = CGAffineTransformMakeRotation(M_PI/2);
[UIView beginAnimations: #"Rotate animation" context: NULL];
MySuperUIImageView.transform = initialPosition;
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationDelegate:self];
MySuperUIImageView.transform = finalPosition;
[UIView commitAnimations];
But after, i made it desappear for a time, using :
MySuperUIImageView.alpha = 0.0f;
And when i re-use it, i want it to be in the first original position, with no rotation. Is it possible easily ?
Thanks in advance !
Yes. Very easily:
MySuperUIImageView.transform = CGAffineTransformIdentity;
Actually, there is. Since you're applying an affine transform to the view, you can reset all transforms applied to the view by setting its transform to CGAffineTransformIdentity which applies an identity transform matrix:
1 - 0 - 0
0 - 1 - 0
0 - 0 - 1
[mySuperUIImageView setTransform:CGAffineTransformIdentity];
Note: In Objective C, the convention is to start class names with a capital letter, and instances with a lower case.
As of iOS 4, Apple recommends using block based UIView animation. Here's an example of what I believe you're trying to attempt using updated code.
CGAffineTransform finalPosition = CGAffineTransformMakeRotation(M_PI/2);
[UIView animateWithDuration:1.0 delay:0.0 options:kNilOptions animations:^{
[mySuperUIImageView setTransform:finalPosition];
} completion:^(BOOL finished) {
[mySuperUIImageView setTransform:CGAffineTransformIdentity];
}];
I am using Slider to Resize and Rotate-
For the Rotate -
CGAffineTransform transform = editingView.transform;
transform = CGAffineTransformMakeRotation(sliderVal * 2*M_PI / 30);
editingView.transform = transform;
For the Resize-
CGAffineTransform t = CGAffineTransformMakeScale(sliderVal/30, sliderVal/30);
CGPoint center = editingView.center;
[UIView animateWithDuration:0.5
animations:^{
editingView.transform = t;
editingView.center = center;
}
completion:^(BOOL finished) {
}];
Using the above code,Both working fine separately.
But I have to resize the rotated view,Or rotate the resized view.
I saw many suggestions coming separate behavior because i am using CGAffineTransformMakeRotation,CGAffineTransformMakeScale,If i use the CGAffineTransformScale,CGAffineTransformRotation then my problem will be solve.
The problem is when I am using CGAffineTransform then scaling is not proper,View disappears from the screen.
You're setting transformation matrix of the view with editingView.transform line.
You should change your code for rotate:
CGAffineTransform transform = editingView.transform;
transform = CGAffineTransformMakeRotation(sliderVal * 2*M_PI / 30);
editingView.transform = CGAffineTransformConcat(editingView.transform, transform);
and for resize:
CGAffineTransform t = CGAffineTransformMakeScale(sliderVal/30, sliderVal/30);
CGPoint center = editingView.center;
[UIView animateWithDuration:0.5
animations:^{
editingView.transform = CGAffineTransformConcat(editingView.transform,t);
editingView.center = center;
}
completion:^(BOOL finished) {
}];
With CGAffineTransformConcat you add 2 transform matrixes together so you won't lose older transforms. You can use CGAffineTransformIdentity to reset the transform.
CGAffineTransform translate = CGAffineTransformMakeTranslation(self.webView.frame.origin.x,self.webView.frame.origin.y - self.webView.frame.size.height * 0.25);
CGAffineTransform scale = CGAffineTransformMakeScale(0.6, 0.6);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
transform = CGAffineTransformRotate(transform, degreesToRadians(-10));
[UIView beginAnimations:#"MoveAndRotateAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:2.0];
editingView.transform = transform;
[UIView commitAnimations];
Try like this...
What I want to do is flip this UIImageView in an instant, no animation, then I need it to float to it's intended position on the screen. Both of the transformations are working, but not the way I want them to.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
resultsEnemy.transform = CGAffineTransformMakeTranslation(0, 0);
[UIView commitAnimations];
resultsEnemy.transform = CGAffineTransformMakeScale(-1, 1);
This is the code I am using. Despite the fact that the scale code (which I am using to flip the UIImageView) is not part of the animation with the 0.5 duration, it is following those rules. How do I avoid this?
Applying two transforms like that isn't going to produce the result you expect. What you need to do is combine them into a single transform matrix. The following should work as expected.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
// Create two separate transforms and concatenate them together.
// Use that new transform matrix to accomplish both transforms at once.
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 0);
CGAffineTransform scale = CGAffineTransformMakeScale(-1, 1);
resultsEnemy.transform = CGAffineTransformConcat(translate, scale);
[UIView commitAnimations];
Edit: Based off of your clarification, you seem to be wanting something like this:
CGAffineTransform scale = CGAffineTransformMakeScale(-1, 1);
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 0);
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
resultsEnemy.transform = scale;
[CATransaction commit];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
resultsEnemy.transform = CGAffineTransformConcat(translate, scale);
[UIView commitAnimations];
I'm trying to translate and scale a view in the same block. For some reason the translate code is over riding the scaling and setting it at 100%. Please help.
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^{
fullView.transform = CGAffineTransformMakeTranslation(0.0, 425.0);
fullView.transform = CGAffineTransformMakeScale(0.8, 0.8);
} completion:^(BOOL finished) { }];
SOLUTION - Change 2 transform lines into one with CGAffineTransformConcat:
fullView.transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(0.0, 425.0), CGAffineTransformMakeScale(0.8, 0.8));
transform is a property that you are setting and then re-setting. What you need to do is construct a CGAffineTransform that consists of a combination of the two transforms. CGAffineTransformConcat() should nicely help you with that.