Getting the rotation angle after CABasicAnimation?

Spinner

I had a view that I rotate a lot, often more than 360 degrees (spins around a few times). Each time it stops, I wanted to determine the resulting “visual” angle. How does one go about doing that?

rotateView is a configured CABasicAnimation:
let rotateView = CABasicAnimation()
let randonAngle = arc4random_uniform(361) + 1440
rotateView.fromValue = 0
rotateView.toValue = Float(randonAngle) * Float(M_PI) / Float(randomBetweenNumbers(firstNum: 90.0, secondNum: 180.0))//180.0
let randomSpeed = randomBetweenNumbers(firstNum: 1.5, secondNum: 2.1)
rotateView.duration = CFTimeInterval(randomSpeed)
rotateView.repeatCount = 0
rotateView.isRemovedOnCompletion = false
rotateView.fillMode = kCAFillModeForwards
rotateView.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
innerRing.layer.add(rotateView, forKey: "transform.rotation.z")

Once done, I dispatch after the randomSpeed duration so I know when the animation will complete. I then wanted the resulting angle. I searched all over the place & found a lot of old broken things and things that didn’t work for me.

This, however, does work (I spent an hour at the late night kitchen table trying things out)…

let transform:CATransform3D = innerRing.layer.presentation()!.transform
let angle: CGFloat = atan2(transform.m12, transform.m11)
var testAngle = radiansToDegress(radians: angle)
if testAngle < 0 {
    testAngle = 360 + testAngle
}
print("final: \(testAngle)ยบ")

// Here is the helper function

func radiansToDegress(radians: CGFloat) -> CGFloat {
    return radians * 180 / CGFloat(M_PI)
}

It rocks. Spin the hell out of your view and get the result using the code above.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.