16

I am having a problem while trying to rotate UIImageview continuously with a ball's image inside. I would like this ball to spin continuously on its center axis. I have tried using CGAffineTransform but it didn't work.

Please help!

Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
orthehelper
  • 4,009
  • 10
  • 40
  • 67
  • Do you need to rotate the ball inside the `UIImageView`? If yes consider using animation methods of the `UIImageView` itself – Manlio Sep 01 '11 at 10:36

2 Answers2

81

This may be an old Q but it's near the top of search results for the topic. Here's a more cut and dry solution: (make sure to import QuartzCore/QuartzCore.h)

CABasicAnimation *rotation;
rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0];
rotation.toValue = [NSNumber numberWithFloat:(2*M_PI)];
rotation.duration = 1.1; // Speed
rotation.repeatCount = HUGE_VALF; // Repeat forever. Can be a finite number.
[yourView.layer addAnimation:rotation forKey:@"Spin"];

Then, to stop remove/reset the animation: (see comments for how to stop-in-place)

[yourView.layer removeAnimationForKey:@"Spin"];

In swift:

let rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.fromValue = 0
rotation.toValue = 2 * M_PI
rotation.duration = 1.1
rotation.repeatCount = Float.infinity
view.layer.addAnimation(rotation, forKey: "Spin")
Christopher Swasey
  • 10,392
  • 1
  • 31
  • 25
  • @Christopher Swasey removing animation key in the middle of animation renders view to original state, not the transformed state. Any way to preserve the transformation ? – atastrophic Jun 09 '13 at 08:23
  • 1
    @tGilani, to preserve the transformation, just add `rotation.removedOnCompletion = NO;` when setting up the CABasicAnimation. This will leave the presentation layer of the animation visible. For more information about the different layers used in iOS animations, I found this post very helpful: [link](http://stackoverflow.com/a/11515749/1114876). – adamup Dec 31 '13 at 05:21
  • 2
    @tGilani, if your animation doesn't have a finite `repeatCount`, you'll need to transform the presentation layer before calling `removeAnimationForKey`. You can do it like this: `yourView.layer.transform = [(CALayer *)[yourView.layer presentationLayer] transform];` – adamup Dec 31 '13 at 05:27
  • @adamup, that last comment did a good thing and a bad thing; on the plus side, YES, that stops it in its tracks (as opposed to resetting it)! However, after adding this line and removing the animation, if I animate the view again, it becomes extremely jumpy and inconsistent. Any ideas why? – Ruben Martinez Jr. Feb 09 '14 at 09:30
  • @RubenMartinezJr. Hmmm - have you tried setting the `fillMode` of the animation to `kCAFillModeForwards`? Using the example in the above answer, it would look like: `rotation.fillMode = kCAFillModeForwards;` This controls the behavior before/after the animation and may have an effect. I can't guess at much more without seeing your code. Hope this helps! – adamup Feb 10 '14 at 22:16
  • It's the exact code here; I start it with one button and stop it with another. I've added in yout suggestion to transform the presentation layer. I'll go ahead and try that and let you know! Thanks! – Ruben Martinez Jr. Feb 11 '14 at 20:12
  • No luck :/ It works well without the presentation layer transformation, but of course jumps on stop. Adding in the transform causes rotation to be jumpy, changes the speed (seemingly) of the rotation next time it is created as well. kCAFillMode didn't seem to have any noticeable effect. – Ruben Martinez Jr. Feb 11 '14 at 20:24
  • @RubenMartinezJr. I managed to fix jumpy animation by setting animation angle ("from" and "to") shifted by current layer's angle: `CGFloat currentAngle = [[_yourView.layer valueForKeyPath:@"transform.rotation.z"] floatValue]; rotation.fromValue = [NSNumber numberWithFloat:currentAngle]; rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI + currentAngle)];` – Murlakatam Feb 27 '14 at 20:38
  • rotation.repeatCount = HUGE_VALF is what I was looking for. Perfect. Thanks. – mondousage Apr 16 '15 at 16:42
  • @Murlakatam This didn't work for me... Still was jumpy after. Alas! currentAngle *did* seem to correctly reflect the last angle, but setting fromValue and toValue as suggested didn't seem to have any discernible difference from not setting them that way. EDIT: This was because I had the cumulative flag set to true on the animation. Not doing so fixed it. YAY! – Ruben Martinez Jr. Feb 12 '16 at 01:01
6

It should work if you use transforms as:

itemToRotate.transform = CGAffineTransformRotate(itemToRotate.transform, currentAngle);

I've uploaded some sample code of a working solution. Add your logic to rotate it automatically...

tipycalFlow
  • 7,594
  • 4
  • 34
  • 45