如果为它设置了 beginTime,CAEmitterLayer 不会添加基本动画

Posted

技术标签:

【中文标题】如果为它设置了 beginTime,CAEmitterLayer 不会添加基本动画【英文标题】:CAEmitterLayer doesn't add basic animation if beginTime was set for it 【发布时间】:2017-03-29 14:32:00 【问题描述】:

我正在尝试使用CAEmitterLayer 和几个CAEmitterCell 为爆炸制作动画。这应该在用户看到视图后的短暂延迟后发生。我在viewDidAppear 开始我的动画。

粒子动画本身可以正常工作,但在这个问题中 Initial particles from CAEmitterLayer don't start at emitterPosition 除非我设置 emitterLayer.beginTime = CACurrentMediaTime() 动画对用户来说似乎已经运行了一段时间。

现在要真正实现爆炸,我必须在某个时刻停止发射粒子。我尝试使用此代码设置CABasicAnimation,它会在一段时间后停止发射器:

// emitter layer is reused (remove all animations, remove all cells, remove from superlayer)
... // emitter layer setup in a function "explode" which is called from viewDidAppear
emitterLayer.beginTime = CACurrentMediaTime()

let birthRateAnimation = CABasicAnimation(keyPath: "birthRate")
birthRateAnimation.toValue = 0
birthRateAnimation.timingFunction = CAMediaTimingFunction.init(name:kCAMediaTimingFunctionEaseOut)
birthRateAnimation.beginTime = CACurrentMediaTime() + 1
birthRateAnimation.duration = 5
birthRateAnimation.delegate = self // (self is view controller)
birthRateAnimation.setValue("expl", forKey: "animName")

emitterLayer.add(birthRateAnimation, forKey: "birthRateAnimation")
self.view.layer.addSublayer(emitterLayer)

所以现在这个代码birthRateAnimation实际上并没有被触发。我登录了animationDidStopanimationDidStart,它们不打印任何内容。

现在,如果我在点击按钮时调用 explode 函数,我根本不会看到 no 粒子动画,但在日志中我会看到“动画开始”/“动画停止”消息。

知道为什么吗?

【问题讨论】:

【参考方案1】:

我发现了两个使动画无法正常工作的问题。

    动画在birthRate上,但CAEmitterLayer没有birthRate属性; CAEmitterCell 确实如此。给您的CAEmitterCell 起一个名字,然后将CABasicAnimation(keyPath: "birthRate") 更改为CABasicAnimation(keyPath: "emitterCells.cellName.birthRate") 将 beginTime 设置为 CACurrentMediaTime() + 1.0 并不能满足您的要求,因为发射器层有自己的时间刻度。将其更改为 emitterLayer.convertTime(CACurrentMediaTime(), from: nil) + 1.0 即可满足您的需求。

【讨论】:

您的 #1 不正确。 CAEmitterLayer 确实有 birthRate。所有细胞的出生率都乘以它。【参考方案2】:

聚会迟到了,但我遇到了同样的事情,解决方案是将发射器的beginTime 设置为CACurrentMediaTime(),例如:

let emitter = makeAwesomeEmitter()
emitter.beginTime = CACurrentMediaTime()

let emitterAnimation = makeAwesomeEmitterBirthRateAnimation()
emitterAnimation.beginTime = 1.0 // 1 sec delay
emitter.add(emitterAnimation, forKey: nil)

myView.layer.addSublayer(emitter)

基本原理是发射器预先生成粒子以模仿它已经运行了一段时间。另请参阅this SO question,它让我找到了解决方案。

【讨论】:

以上是关于如果为它设置了 beginTime,CAEmitterLayer 不会添加基本动画的主要内容,如果未能解决你的问题,请参考以下文章

如何将我的视图控制器设置为它自己的委托?

将 UIScrollView 委托设置为它自己的自定义类

如何使用 CFTimeInterval 为动画指定 beginTime?

有用potplayer的吗?怎么为它配置独立显卡

如何在 QTableview 单元格的值更新后及时为它的颜色设置动画?

iOS:动画多个 UIBezierPaths(一个接一个)?