I'm trying to make a simple "rotating gear animation." Basically, I want to put a circle on the screen at a certain position, and give this circle an image of gear (or just make the image rotating without creating a circle at first). Also, the gear should keep rotating. How can I achieve that?
I'm beginner to ios development. If anyone can provide a simple sample code, I will really appreciate that!
You have to actually rotate a UIImageView infinitely.
Firstly #import <QuartzCore/QuartzCore.h>
- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations: (CGFloat)rotations repeat:(float)repeat;
{
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 = repeat;
[view.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}
Assume that you have a UIImageView and assign an image on it and named ImgView. On viewDidLoad, add your code as below:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationRepeatCount:MAXFLOAT];
ImgView.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
From the links :-
UIView Infinite 360 degree rotation animation?
Infinite rotating image background UIImageView
Related
how the button can be rotated by 360 degree for duration of time 30 sec and after that the button stop rotation.
A 360 rotation animation is only a few lines of code with Core Animation.
CABasicAnimation *rotate =
[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotate.byValue = #(M_PI*2); // Change to - angle for counter clockwise rotation
rotate.duration = 30.0;
[yourButton.layer addAnimation:rotate
forKey:#"myRotationAnimation"];
By using the byValue property you are doing a relative rotation of 360 degrees to whatever rotation was there before (compared to explicitly specifying the from and to values). This means that the above code will rotate the button 360 degrees even if it is already rotated. All the answers that explicitly specify an end transform are assuming that the button isn't already rotated.
The above example is as small as possible to do just what you asked for ("be rotated by 360 degree for duration of time 30 sec"). If you want to have more control you can optionally make the animation start and/or stop slowly by specifying a timing function
rotate.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
If you haven't already added QuarzCore.framework to your project you will need to do so. Also #import <QuartzCore/QuartzCore.h> in the top of your source file.
CATransform3D myRotationTransform = CATransform3DRotate(Yourbutton.layer.transform, -1, 0.0, 0.0, 1.0);
Yourbutton.layer.transform = myRotationTransform;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: -1];
animation.duration = 30;
animation.repeatCount = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[Yourbutton.layer addAnimation:animation forKey:#"MyAnimation"];
Should work as needed! don't forget to include quartz.framework!
Well I just used
Being self.buttonImageView the ImageView you need to rotate.
[UIView animateKeyframesWithDuration:0.5 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(M_PI);
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(-2* M_PI);
}];
} completion:^(BOOL finished) {
[self.map setCenterCoordinate:self.map.userLocation.location.coordinate animated:YES];
self.buttonImageView.transform= CGAffineTransformMakeRotation(2* M_PI);
}];
[UIView animateWithDuration:.30f animations:^{
btnGallery.transform = CGAffineTransformRotate(CGAffineTransformIdentity, -M_PI);
}];
I am rotating the Image 360 clockwise using the CABasicAnimation, and the code which I am using is
CALayer* _caLayer = [CALayer layer];
_caLayer.contents = (id)_logo.CGImage;
_caLayer.frame = CGRectMake(65,158, 180,55);
[self.view.layer addSublayer:_caLayer];
CABasicAnimation* rotation;
rotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0];
rotation.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
rotation.duration = 1.4f;
//rotation.beginTime = CACurrentMediaTime() +1;
rotation.repeatCount = 2.0;
rotation.fillMode = kCAFillModeForwards;
[_caLayer addAnimation:rotation forKey:#"360"];
The animation is working fine.. But I cant figure out one thing. I want to start animate the image from smaller size and ends with the normal size. You have seen in movies like some newspapers will rotate fast and they fade in and finally we will see the paper in the screen fully. I am trying to do that way. I dont know how to do it, please !
You can use the following also, will works like a charm
[UIView beginAnimations:#"fade in" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
_imageView.alpha = 0.0;
_newImageView.alpha = 1.0;
[UIView commitAnimations];
Set the imageView frame before animation: [imageView setFrame: CGRectMake(your Frame)];
then keep on increasing the frame in the animation using a loop or something..
I am trying to present a view by making it emerge from the centre of the screen while growing to its full size, while also rotating it around the x-axis in a 3D manner. When I create the view I apply a transform to it to make sure it is shrunk and rotated to start off with (it is so small it is not actually visible), then I try to use a CATransform3D like this:
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform"];
CATransform3D transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0, 0);
transform = CATransform3DScale(transform, 1000, 1000, 1000);
transform.m34 = 1.0 / 10000;
[anim setToValue:[NSValue valueWithCATransform3D:transform]];
[anim setDuration:0.75f];
anim.removedOnCompletion = NO;
anim.delegate = self;
[view.layer addAnimation:anim forKey:#"grow"];
However this animation does not change the actual transform of the layer, so I also do this:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
view.layer.transform = CATransform3DIdentity;
[view.layer removeAllAnimations];
}
to set the transform once the animation stops. However this sometimes results in a noticeable flicker at the end of the animation. I believe this is because the animation puts the original transform back at the end of the animation phase and this happens momentarily before the animationDidStop routine gets called. Is there a better way to do this?
Edit: Incorporating it into a UIView animation works as this way you can set the transform directly:
view.layer.transform = CATransform3DScale(CATransform3DIdentity, 0.001, 0.001, 0.001);
view.layer.transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0.0, 0.0);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CATransform3D transform = CATransform3DRotate(view.layer.transform, M_PI, 1.0, 0, 0);
transform = CATransform3DScale(rotationTransform, 1000, 1000, 1000);
transform.m34 = 1.0 / -500;
view.layer.transform = transform;
[UIView commitAnimations];
However, I would still like an answer to my original query, as to how to achieve the same successully using a CAAnimation, as that provides more flexibility for animations generally.
Edit2: It seems the answer to my original question (how to fix the problem with the CAAnimation) was actually very straightforward. To keep the end state (and remove the flicker), I just needed to add the following line:
anim.fillMode = kCAFillModeForwards;
This might help you:
animationView.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
animationView.center = CGPointMake(0,
(animationView.center.y -
(animationView.bounds.size.height/2.0f)));
// start the Page Open
[UIView beginAnimations:#"Animation" context:nil];
[UIView setAnimationDuration:2.0];
// set angle as per requirement
[animationView.layer setValue:[NSNumber numberWithInt:180]
forKeyPath:#"transform.rotation.x"];
[UIView commitAnimations];
I know this is not a clean and short answer you were probably hoping for :)
But here (UIView Animation Tutorial: Practical Recipes
) you can find a downloadable example which also shows how to do scale & rotate.
You can see the scale and rotate if you run the example, click HUD and then click stop.
See this thread about how iPad app store does the rotate and scale for an answer and code : How can I flip and enlarge a UIView it at the same time like iOS 7 iPad App Store?
I want to rotate a UIButton continuously as a means of indicating that an app is recording something. Is this a good idea. I also want to be able to stop this continuous rotation.
How would I use animation to do this?
Use the UIView animation method:
animateWithDuration:delay:options:animations:completion:
and use the option UIViewAnimationOptionRepeat
For example for a UIButton * outlet named button:
- (void)viewDidLoad
{
[super viewDidLoad];
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
self.button.transform = transform;
} completion:NULL];
}
Since it's going round and round, I just rotate it by pi radians rather than 2pi. you could use any angle you want.
Edit
To stop the animation, just create another animation of a short duration beginning from the current state, e.g.
- (void)stopRotating {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 0.05);
self.button.transform = transform;
} completion:NULL];
}
This provides a very short animation which overrides the current animation. Note that the angle of the transform is multiplied by 0.05 which is the ratio of 0.1/2.0 which means that the rotational speed for this little segment is the same as the continuous rotational speed.
Try below code that will help you because I run that code successfully.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
CABasicAnimation *halfTurn;
halfTurn = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
halfTurn.fromValue = [NSNumber numberWithFloat:0];
halfTurn.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
halfTurn.duration = 0.5;
halfTurn.repeatCount = HUGE_VALF;
[[button layer] addAnimation:halfTurn forKey:#"180"];
I had the same problem myself. In the end I made it like that:
#pragma mark Start/StopSpining
-(void)startSpin{
isSpining = YES;
[self Spin];
}
-(void)stopSpin{
isSpining = NO;
}
-(void)spin{
[UIView animateWithDuration:1.0 delay:0 options: UIViewAnimationOptionCurveLinear animations:^{
self.spinCircle.transform = CGAffineTransformRotate(self.spinCircle.transform, M_PI/2);
} completion:^(BOOL finished) {
if (isSpining)
[self spin];
}];
}
Try below extension for swift 3.
extension UIView {
func rotate360Degrees(duration: CFTimeInterval = 3) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI * 2)
rotateAnimation.isRemovedOnCompletion = false
rotateAnimation.duration = duration
rotateAnimation.repeatCount=Float.infinity
self.layer.add(rotateAnimation, forKey: nil)
}
}
For start rotation.
MyButton.rotate360Degrees()
And for Stop.
MyButton.layer.removeAllAnimations()
I suggest you don't rotate the UIButton, just the image you put on the button. Who knows what complications or overhead rotating a rectangular object that can detect touches introduces - what happened if your user somehow taps in the corner of the button and then releases the tap as the button has rotated so that the touch is now outside? Does that register a touch up inside or not?
Anyway, if you want continuous rotation use a block method:
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
seems to fit the bill. The complete rotation (2pi) will occur every duration and you cause it to repeat until you stop it using UIViewAnimationOptionRepeat. You can check with completion to see if you should begin another cycle when one animation cycle has ended and you can stop the animation at any time with
[myView.layer removeAllAnimations];
(If you simply want to run it until you stop it then there are other variants of this method without a completion block)
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
uiButtonObject.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
M_PI is the radian value of the angle you want to rotate. Run this in a loop and in a different thread. You might also want to run the above using performSelectorInMainThread method as UI changes are not permitted in the UIThread.
I'm trying to do a simple animation that will rotate an image continuously when a button is clicked, but for some reason when I click the button it crashes the app.
Here's my code.
.h file:
#interface MainView : UIView {
}
IBOutlet UIImageView *sunray;
- (IBAction)pushrotate:(id)sender;
#end
.m file:
#implementation MainView
- (IBAction)pushrotate:(id)sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0];
sunray.transform = CGAffineTransformMakeRotation(6.2831855);
[UIView commitAnimations];
}
-(void) dealloc {
[sunray dealloc];
[sunray release];
[super dealloc];
}
#end
Any idea how I can make it work? Also, what is the best way to make the animation start as soon as the app loads?
If you set your view rotation angle a multiply of 2*PI (it looks so in your case), then the view recognises that transformation does not actually have an effect and view is not rotated.
To rotate your view by angle more then 2*PI with animation you need to use CoreAnimation. So your code should look smth like:
//link with QuartzCore.framework
#import <QuartzCore/QuartzCore.h>
...
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 1.0f;
[sanray.layer addAnimation:animation forKey:#"MyAnimation"];
You probably wired the action or the outlet up wrong (if you posted more console output, we would be sure). See if Interface Builder has any error markers on your actions/outlets.
Also see my comment about calling dealloc yourself - you shouldn't, except for [super dealloc] in your own dealloc implementation.
here is my solution to rotate a image
-(void)rotate:(int)degree {
float rad = M_PI * (float)degree / 180.0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
aktivImageView.transform = CGAffineTransformMakeRotation(rad);
[UIView commitAnimations];
}
i think you can also use this code snip with a button
in your IBAction you can code [self rotate:90]; to rate in 90°
or you can use [self rotate:0]; to not rotate your image ;-)