Как определить определенный прогресс вращения с вращением преобразования CAKeyframeAnimation? - PullRequest
0 голосов
/ 09 июля 2020

Я определил CAKeyframeAnimation для вращения CALayer вдоль оси z. Чтобы анимация работала, я использовал свойства values, keyTimes и duration объекта анимации.

Вот что у меня:

let rotationInDegrees: CGFloat = 7 * 360.0 // 7 times full rotation

let transformationAnimation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
transformationAnimation.values = [0, rotationInDegrees * (CGFloat.pi / 180)]
transformationAnimation.keyTimes = [0, 1]
transformationAnimation.duration = 15

myLayer.add(transformationAnimation, forKey:"transformationAnimation")

Теперь мне нужно выполнить некоторые другие задачи, когда слой поворачивается на каждые x градусов. Я не могу найти способ по своему делу.

Что мне нужно сделать, чтобы получать уведомления о каждом изменении поворота на x градусов?

Я пробовал KVO для наблюдения значений, например:

token = transformationAnimation.observe(\.values) { (anim, values) in
    print(anim.values)
}

Блок наблюдения никогда не запускается.

Также пробовал аналогичный подход, ответивший на в этом вопросе . Но похоже, что предоставленные там решения работают только для "progress" ключа, а не для "transform.rotation.z" (также пробовали с именами ключей "transform" / "transform.rotation", но они также не работают. Даже "transform" выдает значения для прогресса в диапазоне 0,0 ~ 1.0).

Кажется, ни одна из вышеперечисленных попыток не сработала.

1 Ответ

0 голосов
/ 09 июля 2020

Я думаю, что может быть один подход - использовать таймер. KVO недоступен для этих свойств.

Вы можете запустить таймер с началом анимации и непрерывно проверять состояние степени вращения. Ниже указан код -

import PlaygroundSupport
import UIKit

class Animation: NSObject, CAAnimationDelegate {
    
    var timer: Timer?
    
    func doAnimation() {
        let view = UIView.init(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
        view.backgroundColor = UIColor.red
        
        let rotationInDegrees: CGFloat = 7 * 360.0 // 7 times full rotation
        
        let transformationAnimation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
        transformationAnimation.values = [0, rotationInDegrees * (CGFloat.pi / 180)]
        transformationAnimation.keyTimes = [0, 1]
        transformationAnimation.duration = 15
        transformationAnimation.delegate = self
        
        timer = Timer.scheduledTimer(timeInterval: 1.0,
              target: self,
              selector: #selector(eventWith(timer:)),
              userInfo: [ "animation" : transformationAnimation],
              repeats: true)
        
        view.layer.add(transformationAnimation, forKey:"transformationAnimation")
        
        PlaygroundPage.current.needsIndefiniteExecution = true
        PlaygroundPage.current.liveView = view
    }
    
    func animationDidStart(_ anim: CAAnimation) {
        timer?.fire()
    }
    
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        timer?.invalidate()
        timer = nil
    }
    
    // Timer expects @objc selector
    @objc func eventWith(timer: Timer!) {
        if let animation = timer.userInfo as? [String: CAAnimation] {
            print(animation.values)
        }
    }
}

let ballAnimation = Animation()
ballAnimation.doAnimation()
...