【问题标题】:How to detect certain rotation progress with CAKeyframeAnimation transform rotation?如何使用 CAKeyframeAnimation 变换旋转检测某些旋转进度?
【发布时间】:2020-07-09 11:57:35
【问题描述】:

我定义了一个CAKeyframeAnimation 来沿z 轴旋转一个CALayer。为了使动画正常工作,我使用了动画对象的valueskeyTimesduration 属性。

以下是我的:

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)
}

观察块永远不会被触发。


也尝试过类似的方法回答in this question。但似乎那里提供的解决方案只适用于"progress" 键而不适用于"transform.rotation.z"(也尝试使用"transform" / "transform.rotation" 键名,但它们也不起作用。即使"transform" 发出0.0 范围内的进度值~ 1.0)。

上述尝试似乎都不起作用。

【问题讨论】:

    标签: swift calayer caanimation cakeyframeanimation


    【解决方案1】:

    我认为可以有一种方法是使用 Timer。 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()
    

    【讨论】:

    • 嗯,实际上,旋转会比我在示例中显示的要快得多。它可能是每秒 10~20 转左右。因此,我认为在这里使用Timer 不是一个好主意。还因为使用Timer 进行这些动画观察还有其他问题。评论部分in this answer 指出了这一点。
    • 即使我现在选择使用你的方法,我也看不出有任何运气不断检查旋转度的状态你提到的@定时器事件处理方法中的 987654326@ 总是给出在 CAKeyFrameAnimation 对象创建时最初设置的值。
    • 然后,你可以试试这样的stackoverflow.com/questions/18827973/…
    • 是的,在发布这个问题之前我已经尝试过了。但没有运气。似乎,这仅适用于 "progress",但不适用于 "transform.rotation.z"。甚至有趣的是,如果我在 CALayer 的子类中使用“transform”(虽然不是 transform.rotation.z)键,我会得到“progress”的值(范围 0.0 ~ 1.0)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多