Steve Steve - 7 months ago 157
Swift Question

Continuous Rotation of NSImageView (so it appears to be animated)

SWIFT - OSX

I have a bunch of imageViews set in my Main.storyboard. I am trying to make them spin when the app starts and i would like them to indefinitely. I came across the roateByAngle(angle: CGFloat), but this doesn't animate it, instead it just jumps to the new angle.

I would like to make two functions, spinClockwise() and spinAntiClockwise() so I can just call them in the viewDidLoad and they will just keep turning.

Ive been playing with CATransform3DMakeRotation but cannot seem to get my desired results

let width = myImg.frame.width / 2
let height = myImg.frame.height / 2
myImg.layer?.transform = CATransform3DMakeRotation(180, width, height, 1)


Let me know if i can be more specific.
Thanks

Answer

You could add an extension of UIView or UIImageView like this:

extension UIView {

    ///The less is the timeToRotate, the more fast the animation is !
    func spinClockwise(timeToRotate: Double) {
        startRotate(CGFloat(M_PI_2), timeToRotate: timeToRotate)
    }

    ///The less is the timeToRotate, the more fast the animation is !
    func spinAntiClockwise(timeToRotate: Double) {
        startRotate(CGFloat(-M_PI_2), timeToRotate: timeToRotate)
    }

    func startRotate(angle: CGFloat, timeToRotate: Double) {
        UIView.animateWithDuration(timeToRotate, delay: 0.0, options:[UIViewAnimationOptions.CurveLinear, UIViewAnimationOptions.Repeat], animations: {
            self.transform = CGAffineTransformMakeRotation(angle)
            }, completion: nil)
        print("Start rotating")
    }

    func stopAnimations() {
        self.layer.removeAllAnimations()
        print("Stop rotating")
    }
}

So when you want to rotate your myImg, you just have to call:

myImg.spinClockwise(3)

And when you want to stop it:

myImg.stopAnimations()

NOTE: I added a playground just so you can test it out ;)

Cheers!

EDIT:

My bad, Here is the example for NSView:

extension NSView {

    ///The less is the timeToRotate, the more fast the animation is !
    func spinClockwise(timeToRotate: Double) {
        startRotate(CGFloat(-1 * M_PI * 2.0), timeToRotate: timeToRotate)
    }

    ///The less is the timeToRotate, the more fast the animation is !
    func spinAntiClockwise(timeToRotate: Double) {
        startRotate(CGFloat(M_PI * 2.0), timeToRotate: timeToRotate)
    }

    func startRotate(angle: CGFloat, timeToRotate: Double) {

        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = angle
        rotateAnimation.duration = timeToRotate
        rotateAnimation.repeatCount = .infinity

        self.layer?.addAnimation(rotateAnimation, forKey: nil)

        Swift.print("Start rotating")
    }

    func stopAnimations() {
        self.layer?.removeAllAnimations()
        Swift.print("Stop rotating")
    }
}

Important note: Now, after my tests, I noticed that you must set the anchor point of your NSView in the middle so that it can rotate around its center:

view.layer?.anchorPoint = CGPointMake(0.5, 0.5)

I added a new playground with the OSX example