I have this animation in a view based application which a UIImageView that spins 360 for an unlimited amount of time.. But every time the animation is about to end, it "skips."
How would I go about smoothing the animation so there is not skip every time the animation restarts?
Code:
// starts the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// sets the time before animation occurs
// sets the length of the animation
[UIView setAnimationDuration:10.0];
[UIView setAnimationRepeatCount:1e100f]; //spin it forever times.
// 3.14 is pi. -3.14 would be counter clockwise
CGAffineTransform transform = CGAffineTransformMakeRotation(3.14/2);
//square is the UIImageView getting rotated
square.transform = CGAffineTransformRotate(transform, 3.14/2);
// ends animation
[UIView commitAnimations];
If the animation is set to run forever, how is it ever "about to end"? And FYI, you should look at the docs for setAnimationRepeatCount, you don't have to set it to some huge value to get the repeat forever ability.
I have this animation in a view based application which a UIImageView that spins 360 for an unlimited amount of time.. But every time the animation is about to end, it "skips."
How would I go about smoothing the animation so there is not skip every time the animation restarts?
Code:
// starts the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// sets the time before animation occurs
// sets the length of the animation
[UIView setAnimationDuration:10.0];
[UIView setAnimationRepeatCount:1e100f]; //spin it forever times.
// 3.14 is pi. -3.14 would be counter clockwise
CGAffineTransform transform = CGAffineTransformMakeRotation(3.14/2);
//square is the UIImageView getting rotated
square.transform = CGAffineTransformRotate(transform, 3.14/2);
// ends animation
[UIView commitAnimations];
3.14 is not quite pi. It's a little less. There's a constant, M_PI, which is pi to many, many more digits. If you use that, you should get it to make a full 1/2 rotation for each cycle.
What exactly are you getting? Does it rotate 1/2 turn, then jump back to the beginning and start over?
If you specify full rotations using code like this:
Note that your code creates a transform of 3.14/2, and then applies another 3.14/3 rotation to that transform, which results in a total rotation of 3.14, or slightly less than half a full rotation (slightly less because 3.14 is less than pi, which is 3.1415926538...) There's no point in creating a trasnform with CGAffineTransformMakeRotation, and then transforming that transform with CGAffineTransformRotate. You're just making the CPU on the device work a little harder calculating those rotation transformations twice, by half the amount each time.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Ok, I re-did the code to make it a little bit more streamlined. However when I do the (M_PI *2) to go 360˚ the animation does not even start.. Any suggestions?
Ok, I re-did the code to make it a little bit more streamlined. However when I do the (M_PI *2) to go 360˚ the animation does not even start.. Any suggestions?
Hmm. I tested this using a CABasicAnimation on the layer. That works, because you set a rotation key value, rather than applying a rotation to the transform.
I guess you could link 180 degree rotations, where the completion routine (setAnimationDidStopSelector) increments the rotation by 180 degrees and invokes the animation again.
Doing half-turns using UIView animation might look something like this:
Add an iVar to your header:
Code:
CGFloat rotation;
Code:
//Call this method to start the endless spinning animation.
- (void) animateRotation;
{
rotation += M_PI * 2.0 / 3.0;
if (rotation > M_PI * 2)
{
//This probably isn't needed...
rotation -= M_PI * 2;
}
[UIView beginAnimations:nil context:NULL];
//Each 1/3 animation takes 1/3 second, so 1 RPM
[UIView setAnimationDuration:1.0/3.0];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
square.transform = CGAffineTransformMakeRotation(rotation);
//The next 2 calls ask the system to call the
//rotateAnimationDidStop:finished:context: method once the animation
//is complete
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector:
@selector(rotateAnimationDidStop:finished:context:)];
[UIView commitAnimations];
}
- (void)rotateAnimationDidStop: (NSString *) animationID
finished: (NSNumber *) finished
context: (void *)context;
{
[self animateRotation]; //start another 180 degree rotation
}
EDIT: There were several problems with the UIView animation code I posted.
1. The UIView animation uses a transform, and applies an increasing rotation to that transform. I posted code that increased the rotation by 180° (M_PI) per step. The system can't tell if a 180° change is supposed to be clockwise or counter-clockwise, so it gets confused and rotates back and forth instead of spinning.. I needed to change the rotation to 2/3 ∏ per step (a third of a rotation) so the system can tell which way to animate it. I changed the code above accordingly.
2. Since this code uses a did stop method to repeat the animation when it finishes, we don't want a repeat count.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.