iOS 动画二十四:粒子系统 Particle Emitters
瀑布,火焰,烟雾和雨水效果都涉及大量的粒子 - 它们具有共同的物理特征,也具有自己独特的尺寸,方向,旋转和轨迹。
粒子可以很好地创建逼真的效果,因为每个粒子都可以是随机的和不可预测的。 例如,暴风雨中的每个雨滴可能具有独特的大小,形状和速度。
iOS 粒子系统有以下几种常用发射类型:
1. Point shape
kCAEmitterLayerPoint 的发射器形状会导致所有粒子在同一点创建。 对于涉及烟花的效果,这是一个很好的选择。我们可以通过在同一点创建粒子并在它们消失之前使它们沿不同方向飞行来创建烟花效果。
Point shape2. Line shape
这是一种用于瀑布效果的发射器形状; 水粒子出现在瀑布的顶部边缘并向下级联:
Line shape
3. Rectangle shape
kCAEmitterLayerRectangle 的发射器形状通过给定的矩形区域随机创建粒子:
Rectangle shape
这种发射器形状非常适合许多不同的效果,例如碳酸饮料中的气泡。
除了以上几种类型,还有 cuboid, circle and sphere 等发射类型。欲知更多,请查阅相关资料。
Particle Emitters 相关属性设置:
1. Adding an emitter frame
emitter.emitterPosition = CGPoint(x: rect.width/2, y: rect.height/2)
emitter.emitterSize = rect.size
结合形状,位置和尺寸属性定义发射器框架。 这里,可以将发射器的位置设置为图层的中心,并将发射器大小设置为等于图层的大小。like so:
entire layer frame2. Creating an emitter cell
emitter cell 是表示一个粒子源的数据模型,它与 CAEmitterLayer 是不同的类,单个 emitter layer 可以包含一个或多个 cells。
例如,在爆米花动画中,可以有三个不同的 cells 来代表爆米花内核的不同状态:完全爆开、半爆开和那些顽固的未爆开:
爆米花状态粒子发射器示例:
particle emitters3. Controlling your particles
// add a little acceleration in the y-direction so the particles will drift downwards like real snow.
emitterCell.yAcceleration = 70.0
// snowflakes should be moving in a downward diagonal direction
emitterCell.xAcceleration = 10.0
emitterCell.velocity = 20.0
emitterCell.emissionLongitude = .pi * -0.5
发射经度 emissionLongitude 是粒子的初始角度,velocity 参数设置粒子的初始速度,如下所示:
发射经度4. Adding randomness to your particles
设置发射器随机范围:
emitterCell.velocityRange = 200.0
每个粒子的速度将是(20-200)= -180 和(20 + 200)之间的随机值。
初始速度为负的粒子根本不会上升,一旦它们出现在屏幕上,它们就会开始向下移动。 具有正速度的粒子则将首先向上移动,然后向下移动。
emitterCell.emissionRange = .pi * 0.5
确保所有粒子在出现时以-π/ 2角度直接向上发射。上面的代码指示发射器在(-π/ 2 - π/ 2)= 180度和(-π/ 2 +π/ 2)= 0 度范围内为每个粒子挑选一个随机角度,如下图所示:
5. Changing particle color
emitterCell.color = UIColor(red: 0.9, green: 1.0, blue: 1.0, alpha: 1.0).cgColor
// 颜色范围
emitterCell.redRange = 0.3
emitterCell.greenRange = 0.3
emitterCell.blueRange = 0.3
绿色和蓝色分量值现在是 0.7 到 1.3 之间的随机值,但是,高于 1.0 的值的上限为 1.0,因此有效范围为 0.7 到 1.0。 红色成分,因为其 “normal” 值为 0.9,所以它的上限介于 0.6 和 1.0 之间。 这些是相对较窄的范围,因此产生的随机颜色看上去差异不大。
6. Randomizing particle appearance
emitterCell.scale = 0.8
emitterCell.scaleRange = 0.8
这样可以产生大到比原始尺寸大 1.6 倍的大雪花,小到零尺寸的雪花。
emitterCell.scaleSpeed = -0.15
指示粒子按每秒 15% 比例缩小。
当雪花接近屏幕的下半部分时,雪花会越来越小。 这是一个很 nice 的效果。
emitterCell.alphaRange = 0.75
emitterCell.alphaSpeed = -0.15
设置一个宽的 alpha 范围,从 0.25 到 1.0 。 alphaSpeed与 scaleSpeed 非常相似,可以随时间更改粒子的 alpha 值。
7. Adding some final polish
emitterCell.emissionLongitude = -.pi
发射经度 emissionLongitude 是发射粒子的起始角。 初始角度改为 -.pi 角度,会让雪花有像被风吹动的效果。
附:主要代码:
// creates a new CAEmitterLayer, sets the layers’ frame to take up the full width of the screen and positions the layer near the top of the screen.
let rect = CGRect(x: 0.0, y: -70.0, width: view.bounds.width, height: 50.0)
let emitter = CAEmitterLayer()
emitter.frame = rect
view.layer.addSublayer(emitter)
// The shape of your emitter generally affects the area where new particles are being created
emitter.emitterShape = kCAEmitterLayerRectangle
emitter.emitterPosition = CGPoint(x: rect.width/2, y: rect.height/2)
emitter.emitterSize = rect.size
// create a new cell and set flake.png as its contents. The contents property holds the template from which new particles will be created.
let emitterCell = CAEmitterCell()
emitterCell.contents = UIImage(named: "flake.png")?.cgImage
// 每秒创建 20 个雪花,并将它们保持在屏幕上 3.5 秒。 这意味着除了动画的最初几秒,在任何给定时间屏幕上将有 70 个雪花。
emitterCell.birthRate = 20
emitterCell.lifetime = 3.5
// add a little acceleration in the y-direction so the particles will drift downwards like real snow.
emitterCell.yAcceleration = 70.0
// snowflakes should be moving in a downward diagonal direction
emitterCell.xAcceleration = 10.0
emitterCell.velocity = 20.0
emitterCell.emissionLongitude = .pi * -0.5
emitterCell.velocityRange = 200.0
emitterCell.emissionRange = .pi * 0.5
emitterCell.color = UIColor(red: 0.9, green: 1.0, blue: 1.0, alpha: 1.0).cgColor
emitterCell.redRange = 0.1
emitterCell.greenRange = 0.1
emitterCell.blueRange = 0.1
emitterCell.scale = 0.8
emitterCell.scaleRange = 0.8
emitterCell.scaleSpeed = -0.15// The scaleSpeed property above instructs your particles to scale down by 15% of their original size per second
emitterCell.alphaRange = 0.75
emitterCell.alphaSpeed = -0.15
emitterCell.emissionLongitude = -.pi
// 因为 emitterCell.lifetime = 3.5,lifetimeRange = 1.0 将每个雪的生命周期设置为 2.5 到 4.5 秒之间的随机值。
emitterCell.lifetimeRange = 1.0
//cell #2
let cell2 = CAEmitterCell()
cell2.contents = UIImage(named: "flake2.png")?.cgImage
cell2.birthRate = 50
cell2.lifetime = 2.5
cell2.lifetimeRange = 1.0
cell2.yAcceleration = 50
cell2.xAcceleration = 50
cell2.velocity = 80
cell2.emissionLongitude = .pi
cell2.velocityRange = 20
cell2.emissionRange = .pi * 0.25
cell2.scale = 0.8
cell2.scaleRange = 0.2
cell2.scaleSpeed = -0.1
cell2.alphaRange = 0.35
cell2.alphaSpeed = -0.15
cell2.spin = .pi
cell2.spinRange = .pi
//cell #3
let cell3 = CAEmitterCell()
cell3.contents = UIImage(named: "flake3.png")?.cgImage
cell3.birthRate = 20
cell3.lifetime = 7.5
cell3.lifetimeRange = 1.0
cell3.yAcceleration = 20
cell3.xAcceleration = 10
cell3.velocity = 40
cell3.emissionLongitude = .pi
cell3.velocityRange = 50
cell3.emissionRange = .pi * 0.25
cell3.scale = 0.8
cell3.scaleRange = 0.2
cell3.scaleSpeed = -0.05
cell3.alphaRange = 0.5
cell3.alphaSpeed = -0.05
emitter.emitterCells = [emitterCell, cell2, cell3]
雪花效果