如何修改CAEmitterLayer中CAEmitterCell内容及停止移除发射器
问题解答
1. 修改CAEmitterLayer的发射器图片
问题原因
当你将CAEmitterCell赋值给CAEmitterLayer的emitterCells数组时,图层会对传入的cell进行复制。后续修改全局变量myEmitterCell的属性,并不会影响图层中正在使用的cell实例,所以图片不会更新。
解决方案
直接操作图层中的cell实例,修改后重新赋值给emitterCells触发更新:
@objc func myEmitterChange() { print("Did I Change?") // 从发射器层中获取当前使用的cell guard let currentCell = myEmitterLayer.emitterCells?.first else { return } // 安全获取图片,避免nil崩溃 guard let newImage = UIImage(named: "myImage2")?.cgImage else { return } // 修改cell属性 currentCell.color = UIColor.orange.cgColor currentCell.contents = newImage // 重新赋值emitterCells,触发图层更新 myEmitterLayer.emitterCells = [currentCell] }
如果需要循环切换图片,可以维护一个图片名称数组和当前索引:
// 新增属性 private let imageNames = ["myImage1", "myImage2", "myImage3"] private var currentImageIndex = 0 @objc func myEmitterChange() { print("Did I Change?") guard let currentCell = myEmitterLayer.emitterCells?.first else { return } currentImageIndex = (currentImageIndex + 1) % imageNames.count guard let newImage = UIImage(named: imageNames[currentImageIndex])?.cgImage else { return } currentCell.contents = newImage myEmitterLayer.emitterCells = [currentCell] // 继续循环切换,每隔10秒调用一次 self.perform(#selector(self.myEmitterChange), with: nil, afterDelay: 10) }
2. 停止并彻底移除CAEmitterLayer
解决方案
需要先停止新粒子的生成,再移除图层(可选等待现有粒子消失后再移除):
@objc func stopAndRemoveEmitter() { // 1. 停止生成新粒子 myEmitterLayer.birthRate = 0 // 2. 等待现有粒子生命周期结束(根据你设置的lifetime=15秒)后移除图层 DispatchQueue.main.asyncAfter(deadline: .now() + 15) { self.myEmitterLayer.removeFromSuperlayer() // 可选:重置全局变量,避免后续引用问题 self.myEmitterLayer = CAEmitterLayer() self.myEmitterCell = CAEmitterCell() } // 如果不需要等待粒子消失,直接移除: // myEmitterLayer.removeFromSuperlayer() }
说明
- 设置
birthRate = 0会立即停止发射器产生新的粒子,但已经存在的粒子会继续播放直到生命周期结束。 - 若不需要等待现有粒子消失,直接调用
removeFromSuperlayer()即可,但此时屏幕上的粒子会突然消失。
内容的提问来源于stack exchange,提问作者user4806509
相关产品推荐
相关产品推荐

