Steve
Steve

Reputation: 5005

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

Upvotes: 2

Views: 1795

Answers (2)

Burak
Burak

Reputation: 516

For me, I could not change the anchor point. It was spinning around (0,0) which is bottom left. I moved the anchor point to (0.5, 0.5), but still no luck. Then I came accross with this answer. I modified my code like below, and it begins to rotate around itself. I observed a drawback though, the place of the view somehow shifted, but it can be fixed by trial and error, trying to get it to the right place.

extension NSView {

    func startRotating(duration: Double = 1) {

        let kAnimationKey = "rotation"

        //self.wantsLayer = true
        if layer?.animation(forKey: kAnimationKey) == nil {
            var oldFrame = self.frame
            self.layer?.anchorPoint = CGPoint(x: 1, y: 1)
            self.frame = oldFrame

            let animate = CABasicAnimation(keyPath: "transform.rotation")
            animate.duration = duration
            animate.repeatCount = Float.infinity
            animate.fromValue = 0.0
            animate.toValue = Double.pi * 2.0
            self.layer?.add(animate, forKey: kAnimationKey)

            oldFrame = self.frame
            self.layer?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
            self.frame = oldFrame
        }


     }
}

Upvotes: 1

Mindhavok
Mindhavok

Reputation: 457

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

Upvotes: 2

Related Questions