如何使用 CAKeyframeAnimation 变换旋转检测某些旋转进度?
Posted
技术标签:
【中文标题】如何使用 CAKeyframeAnimation 变换旋转检测某些旋转进度?【英文标题】:How to detect certain rotation progress with CAKeyframeAnimation transform rotation? 【发布时间】:2020-07-09 11:57:35 【问题描述】:我定义了一个CAKeyframeAnimation
来沿z 轴旋转一个CALayer
。为了使动画正常工作,我使用了动画对象的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)
观察块永远不会被触发。
也尝试过类似的方法回答in this question。但似乎那里提供的解决方案只适用于"progress"
键而不适用于"transform.rotation.z"
(也尝试使用"transform"
/ "transform.rotation"
键名,但它们也不起作用。即使"transform"
发出0.0 范围内的进度值~ 1.0)。
上述尝试似乎都不起作用。
【问题讨论】:
【参考方案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
对象创建时最初设置的值。
然后,你可以试试这样的***.com/questions/18827973/…
是的,在发布这个问题之前我已经尝试过了。但没有运气。似乎,这仅适用于 "progress",但不适用于 "transform.rotation.z"。甚至有趣的是,如果我在 CALayer
的子类中使用“transform”(虽然不是 transform.rotation.z)键,我会得到“progress”的值(范围 0.0 ~ 1.0)。以上是关于如何使用 CAKeyframeAnimation 变换旋转检测某些旋转进度?的主要内容,如果未能解决你的问题,请参考以下文章
CAKeyframeAnimation 完成时如何指定选择器?
如何在 Iphone 中停止 CAKeyFrameAnimation
如何同步几个不同图层的 CAKeyframeAnimation 动画?
如何获取CAKeyframeAnimation对象的当前屏幕xy位置?