iOS 动画二十四:粒子系统 Particle Emitters

瀑布,火焰,烟雾和雨水效果都涉及大量的粒子 - 它们具有共同的物理特征,也具有自己独特的尺寸,方向,旋转和轨迹。

粒子可以很好地创建逼真的效果,因为每个粒子都可以是随机的和不可预测的。 例如,暴风雨中的每个雨滴可能具有独特的大小,形状和速度。

iOS 粒子系统有以下几种常用发射类型:
1. Point shape

kCAEmitterLayerPoint 的发射器形状会导致所有粒子在同一点创建。 对于涉及烟花的效果,这是一个很好的选择。我们可以通过在同一点创建粒子并在它们消失之前使它们沿不同方向飞行来创建烟花效果。

Point shape
2. 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 frame
2. Creating an emitter cell

emitter cell 是表示一个粒子源的数据模型,它与 CAEmitterLayer 是不同的类,单个 emitter layer 可以包含一个或多个 cells。

例如,在爆米花动画中,可以有三个不同的 cells 来代表爆米花内核的不同状态:完全爆开、半爆开和那些顽固的未爆开:

爆米花状态
粒子发射器示例:
particle emitters
3. 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]
雪花效果

demo下载

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容