How to rotate image 360 degrees endlessly using iPhone SDK? - iphone

I want to rotate image 360 degrees endlessly using iPhone SDK?
How can this be done?
Thanks!

-(void)startAnimationWithRevolutions:(float)revPerSecond forTime:(float)time
{
spinWheel.userInteractionEnabled = FALSE;
float totalRevolutions = revPerSecond * time;
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:time] forKey:kCATransactionAnimationDuration];
CABasicAnimation* spinAnimation = [CABasicAnimation
animationWithKeyPath:#"transform.rotation"];
CGAffineTransform transform = spinWheel.transform;
float fromAngle = atan2(transform.b, transform.a);
float toAngle = fromAngle + (totalRevolutions*4*M_PI);
spinAnimation.fromValue = [NSNumber numberWithFloat:fromAngle];
spinAnimation.toValue = [NSNumber numberWithFloat:toAngle];
spinAnimation.repeatCount = 0;
spinAnimation.removedOnCompletion = NO;
spinAnimation.delegate = self;
spinAnimation.timingFunction = [CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseOut];
[spinWheel.layer addAnimation:spinAnimation forKey:#"spinAnimation"];
[CATransaction commit];
}
Try using this, it works.

Assuming you are displaying the image in a UIImageView, you can rotate the view's local coordinate system (see here) and use NSTimer to increase the rotation periodically (see here).
(I would use OpenGL for this, but that's just a personal preference and is probably overkill for your situation.)

Related

How to move and rotate object in iphone

I am developing a small game in iphone... Game concept is place an object in top of the bar...Rotating a bar using accelerometer. When bar rotating , i need to move an object with respect to bar. How to implement this concept...Any examples or references?
Rotating both img:
barImg,objImg //UIImageView
barImg.transform = CGAffineTransformMakeRotation(Ypos);
objImg.transform=CGAffineTransformMakeRotation(Ypos);
So for rotating 360 Degree with animation:
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:-M_PI * 2.0]; // full rotation*/ * rotations * duration ];
rotationAnimation.duration = 1;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = MAXFLOAT;
[rotatingTelIamgeview.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
you can play with toValue for changing the angle.
For moving an object:
CGPoint startPoint = CGPointMake(lvMessageInputBar.animationBubbleImageView.layer.frame.origin.x+lvMessageInputBar.animationBubbleImageView.layer.frame.size.width/2
, lvMessageInputBar.animationBubbleImageView.layer.frame.origin.y +lvMessageInputBar.animationBubbleImageView.layer.frame.size.height/2 );
CGPoint endPoint = CGPointMake(endPoint.origin.x+Endpoint.size.width/2, bubleRect.origin.y+bubleRect.size.height/2);
CGPoint middlePoint = // any point between start and end corrdinates
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
CGPathAddQuadCurveToPoint(path, NULL,middlePoint.x, middlePoint.y,endPoint.x,endPoint.y);
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.delegate = self;
pathAnimation.removedOnCompletion = NO;
pathAnimation.path = path;
[pathAnimation setCalculationMode:kCAAnimationCubic];
[pathAnimation setFillMode:kCAFillModeForwards];
pathAnimation.duration = 0.3;
[lvMessageInputBar.animationBubbleImageView.layer addAnimation:pathAnimation forKey:nil];
The above example moves the layer of the object over a path.but CGPathAddQuadCurveToPoint makes the path not diagonal rather circular path (curve).
you can use CGPathAddPath if you do not want this effect.
If you are new to iPhone I would start with layer tutorial to get the idea behind CALayer and then take a look CALayer animations
CALayers introduction:
https://www.raywenderlich.com/3096-calayers-tutorial-for-ios-introduction-to-calayers
CALayer Animation documentation of from Apple:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html
You can also watch Session 424 (Core Animation in Practice, Part 1) and 425 (Core Animation in Practice, Part 2) of WWDC 2010:
https://developer.apple.com/videos/archive/

Rotating animation

I'm rotating an arrow by 45 degrees. When an animation ends, the arrow returns to its original state (0 degrees). I need that the arrow doesn't return to original state and it will be rotate by 45 degrees at the end of animation.
CABasicAnimation *fullRotationShort = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
fullRotationShort.fromValue = [NSNumber numberWithFloat:0];
fullRotationShort.toValue = [NSNumber numberWithFloat:M_PI/28*4.7];
fullRotationShort.duration = 1.0f;
fullRotationShort.repeatCount = 1;
[imgViewArrowShort.layer addAnimation:fullRotationShort forKey:nil];
Assuming your arrow is a UIImageView named arrow.
You really don't need such complicated CAAnimations for this.
[UIView animateWithDuration:1.0 animations:^{
arrow.transform = CGAffineTransformMakeRotation(0.25 * M_PI);
}];
Set the property:
fullRotationShort.fillMode = kCAFillModeForwards;
fullRotationShort.cumulative = YES;
fullRotationShort.removedOnCompletion=NO;

CABasicAnimation Problem

So, I have read in the docs, that use of blocks like
beginAnimation
commitAnimation
is discouraged from os4.0.
So I have tried to get my code to work by using CABasicAnimation. I want to achieve, that an image's frame is resized from its thumbnail size, somewhere within my view, to a full width position e.g. (0, 120, 320, 240) - on my iPhone.
What I have so far:
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:1.0] forKey:kCATransactionAnimationDuration];
CABasicAnimation *scalingAnimation;
scalingAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
scalingAnimation.duration=1.0/2;
scalingAnimation.autoreverses=YES;
scalingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
scalingAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
scalingAnimation.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeScale(4, 4, 1)];
[b.layer addAnimation:scalingAnimation forKey:#"scaling"];
[CATransaction commit];
My nextstep would be to first try to move the image to a centered position then scale it to the correct size. However, I doubt I'm doin it the right way. Can anyone comment on my code/approach.... is there a better way?
Am pretty sure you have solved this by now, but in any case.
You shouldn't need the [CATransaction begin]; and [CATransaction commit];
The simplest way that I have found to do this kind of thing is to use CAAnimationGroup and and add the animations one by one.
An example would be
CABasicAnimation *scaleX = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
//this is not used, as the group provides the duration
scaleX.duration = duration;
scaleX.autoreverses = NO;
scaleX.toValue = [NSNumber numberWithFloat:1.0];
scaleX.fromValue = [NSNumber numberWithFloat:scaleFrom];
scaleX.fillMode = kCAFillModeForwards;
scaleX.removedOnCompletion = NO;
CABasicAnimation *scaleY = [CABasicAnimation animationWithKeyPath:#"transform.scale.y"];
//this is not used, as the group provides the duration
scaleY.duration = duration;
scaleY.autoreverses = NO;
scaleY.toValue = [NSNumber numberWithFloat:1.0];
scaleY.fromValue = [NSNumber numberWithFloat:scaleFrom];
scaleY.fillMode = kCAFillModeForwards;
scaleY.removedOnCompletion = NO;
//add in the translation animations
NSMutableArray* animationsArray = [NSMutableArray arrayWithObjects:scaleX,
scaleY,
//and any other animations you want in the group
nil];
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 1.0/2;
animationGroup.timingFunction = [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];
animationGroup.animations = animationsArray;
animationGroup.delegate = self;
animationGroup.removedOnCompletion = YES;
animationGroup.fillMode = kCAFillModeForwards;
[animationGroup setValue:#"imageTransform" forKey:#"AnimationName"];
[b.layer addAnimation:animationGroup forKey:#"imageTransform"];
There are a few gotchas though. Animations are purely visual, so before running the animations, set your eventual view frame.
You will notice that the scales end at 1, this is to ensure that you dont end up with a scaled image layer. Instead we start it scaled and bring it back to normal.
Translations should be done in the same way.
Hope this helps
//in Event Method Copy Below code to place the image to the center
CABasicAnimation* positionAnimation;
positionAnimation = [CABasicAnimation animationWithKeyPath:#"position"];
positionAnimation.fromValue = [NSValue valueWithCGPoint:imageView.layer.position];
positionAnimation.toValue = [NSValue valueWithCGPoint:centerPointofView];
positionAnimation.duration = 2.0;
positionAnimation.fillMode = kCAFillModeForwards;
positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
positionAnimation.removedOnCompletion = NO;
positionAnimation.delegate = self;
[imageView.layer addAnimation:positionAnimation forKey:#"positionAnimation"];
// For Scale After image is in center copy below code
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{
CAAnimation *animation = [imageView.layer animationForKey:#"positionAnimation"];
if (animation == theAnimation)
{
CABasicAnimation* scaleAnimation;
scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.fromValue = [NSNumber numberWithFloat:1];
scaleAnimation.toValue = [NSNumber numberWithFloat:4.0];
scaleAnimation.duration = 2.2;
scaleAnimation.fillMode = kCAFillModeForwards;
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
scaleAnimation.removedOnCompletion = NO;
scaleAnimation.delegate = self;
[imageView.layer addAnimation:scaleAnimation forKey:#"scaleAnimation"];
}
else
{
//if you want changes to image should remain forever
//place your code for scale & transform here
....................
//now simple remove animation from layer
[imageView.layer removeAllAnimations];
}
}
Cant you use
[UIView animateWithDuration:2.0
animations:^{
//animations
}
completion:^(BOOL finished){
// completion methods
}];

smooth pendular animation with Core Animation Framework

im trying to do an animation with an uiimageview.
in this view is an image with an arrow, that i want to rotate about 45 degrees back and forward very smoothly like an pendular or an old clock.
something like this, just smooth and with my image: http://bit.ly/cArvNw (found this with google ;) )
my current setup looks like this:
UIImageView* rotatingImage = [[UIImageView alloc] initWithFrame:CGRectMake(10.0, 10.0, 200.0, 200.0)];
[rotatingImage setImage:[UIImage imageNamed:#"wind.png"]];
CALayer *layer = rotatingImage.layer;
CAKeyframeAnimation *animation;
animation = [CAKeyframeAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.duration = 0.5f;
animation.cumulative = YES;
animation.repeatCount = 100;
animation.values = [NSArray arrayWithObjects: // i.e., Rotation values for the 3 keyframes, in RADIANS
[NSNumber numberWithFloat:[self degreesToRadians:45.0]],
[NSNumber numberWithFloat:[self degreesToRadians:-45.0]], nil];
animation.keyTimes = [NSArray arrayWithObjects: // Relative timing values for the 3 keyframes
[NSNumber numberWithFloat:0],
[NSNumber numberWithFloat:.5], nil];
animation.timingFunctions = [NSArray arrayWithObjects:
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], // from keyframe 1 to keyframe 2
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], nil]; // from keyframe 2 to keyframe 3
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[layer addAnimation:animation forKey:nil];
[self addSubview:rotatingImage];
this is really a pain, add 45 degrees, then 45 degrees backward with "-45" doesnt work.
im very new to core animation and dont know how to setup my code, to get my wanted animation.
can anybody help please?
Have you looked at Apple's Example iPhone Application, "Metronome"?
It does almost exactly what you're trying to do, using Core Animation.
Note: This method does not use Core Animation, but it's very simple and probably uses less resources.
First, make the UIImageView twice as tall, thereby making the center of rotation equal to the center of the image.
Then, define these in the #interface of the header file (of, say, your UIViewController):
BOOL goingCW; // going clockwise = YES, going counterclockwise = NO
CGFloat angle; // angle by which to change the image's rotation value
Then put this in an init method that runs once:
goingCW = YES; // change this to NO to make it start rotating CCW instead
angle = 0;
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(update) userInfo:nil repeats:YES];
Then define update, given that arrow is the UIImageView instance:
- (void)update {
if (goingCW) {
if (angle > M_PI / 4) goingCW = NO; // M_PI / 4 is equal to 45 degrees
angle += M_PI / 60; // increase 60 to slow down the rotation, etc.
} else {
if (angle < -M_PI / 4) goingCW = YES; // -M_PI / 4 is equal to -45 degrees
angle -= M_PI / 60; // increase 60 to slow down the rotation, etc.
}
// rotate the UIImageView appropriately
arrow.transform = CGAffineTransformMakeRotation(angle);
}
This also assumes that you are starting in the facing-down position.

Moving Image 360 Degree

How can we Move an Image 360 Degree from the starting point to the ending point?
Moving Image 360 Degree?
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"];
}
A 360 degree rotation in any axis leaves the view unchanged. So don't touch the image, and you're good to go!
You could use an animation function (CAValueFunction) for this too:
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
rotationAnimation.duration = duration;
rotationAnimation.fromValue = [NSNumber numberWithFloat:0.0];
rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0];
rotationAnimation.valueFunction = [CAValueFunction functionWithName:kCAValueFunctionRotateZ];
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[myView.layer addAnimation:rotationAnimation forKey:nil];