iOS实现粒子发射动画效果图

代码已上传 GitHub:https://www.easck.com// 从发射器的轮廓发射粒子 rainLayer.emitterMode = kCAEmitterLayerOutline // 优先渲染旧的粒子 rainLayer.renderMode = kCAEmitterLayerOldestFirst // 发射位置 // 对于线形发射器,线的两端点分别为 // (emitterPosition.x - emitterSize.width/2, emitterPosition.y, emitterZPosition)和 // (emitterPosition.x + emitterSize.width/2, emitterPosition.y, emitterZPosition) rainLayer.emitterPosition = CGPoint(x: view.bounds.midX, y: 0) // 发射器大小 rainLayer.emitterSize = CGSize(width: view.bounds.width, height: 0) // 粒子生成速率的倍数,一开始不发射,设置为零 rainLayer.birthRate = 0 // 发射的粒子 let cell = CAEmitterCell() // 粒子显示的内容,设置CGImage,显示图片 cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage // 粒子缩放倍数 cell.scale = 0.1 // 粒子寿命,单位是秒 cell.lifetime = 5 // 粒子生成速率,单位是个/秒,实际显示效果要乘以CAEmitterLayer的birthRate cell.birthRate = 1000 // 粒子速度 cell.velocity = 500 // 粒子发射角度,正值表示顺时针方向 cell.emissionLongitude = CGFloat.pi // 图层要发射1种粒子 rainLayer.emitterCells = [cell] // 添加粒子发射图层 view.layer.addSublayer(rainLayer) }
点击按钮开始或停止动画。用 CABasicAnimation 使粒子生成速率的倍数渐变,达到雨逐渐变大或变小的效果
@IBAction func rainButtonClicked(_ sender: UIButton) {
// 连续调用此方法会影响雨变大或变小的连贯性,所以禁止连续点击按钮
sender.isUserInteractionEnabled = false
// 粒子生成速率渐变动画
let birthRateAnimation = CABasicAnimation(keyPath: "birthRate")
birthRateAnimation.duration = 3
if rainLayer.birthRate == 0 {
// 雨变大
birthRateAnimation.fromValue = 0
birthRateAnimation.toValue = 1
rainLayer.birthRate = 1
} else {
// 雨变小
birthRateAnimation.fromValue = 1
birthRateAnimation.toValue = 0
rainLayer.birthRate = 0
}
// 加入动画
rainLayer.add(birthRateAnimation, forKey: "birthRate")
// 动画时长过后恢复按钮可点击状态
DispatchQueue.main.asyncAfter(deadline: .now() + birthRateAnimation.duration) { [weak self] in
guard self != nil else { return }
sender.isUserInteractionEnabled = true
}
}
发射一圈粒子动画效果
给控制器添加类型为 CAEmitterLayer 的属性 centerHeartLayer,在 viewDidLoad 方法中对此属性进行初始化
private var centerHeartLayer: CAEmitterLayer!
private func setupCenterHeartLayer() {
centerHeartLayer = CAEmitterLayer()
// 发射器形状为圆形,默认向四周发射粒子
centerHeartLayer.emitterShape = kCAEmitterLayerCircle
centerHeartLayer.emitterMode = kCAEmitterLayerOutline
centerHeartLayer.renderMode = kCAEmitterLayerOldestFirst
// 发射器位置
// 对于圆形发射器
// 圆心位于(emitterPosition.x, emitterPosition.y, emitterZPosition)
// 半径为emitterSize.width
centerHeartLayer.emitterPosition = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
centerHeartLayer.emitterSize = centerHeartButton.frame.size
centerHeartLayer.birthRate = 0
let cell = CAEmitterCell()
cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage
cell.lifetime = 1
cell.birthRate = 2000
cell.scale = 0.05
// 粒子缩放倍数每秒减小0.02,粒子逐渐缩小
cell.scaleSpeed = -0.02
// 粒子透明度每秒减小1,粒子逐渐变透明
cell.alphaSpeed = -1
cell.velocity = 30
centerHeartLayer.emitterCells = [cell]
view.layer.addSublayer(centerHeartLayer)
}










