CAEmitterLayer 是一個高性能的粒子引擎登刺,被用來創(chuàng)建復(fù)雜的粒子動畫如:煙霧籽腕,火,雨等效果纸俭,并且很好地控制了性能皇耗。
蘋果給出的解釋是:
CAEmitterLayer 看上去像是許多 CAEmitterCell 的容器,這些 CAEmitterCell 定義了一個例子效果揍很。你將會為不同的例子效果定義一個或多個 CAEmitterCell 作為模版郎楼,同時 CAEmitterLayer 負(fù)責(zé)基于這些模版實(shí)例化一個粒子流。一個 CAEmitterCell 類似于一個 CALayer :它有一個 contents 屬性可以定義為一個 CGImage 窒悔,另外還有一些可設(shè)置屬性控制著表現(xiàn)和行為呜袁。
以上解釋來源于網(wǎng)絡(luò)
我來舉個通俗易懂的例子吧CAEmitterLayer就像大炮,決定了(1)哪里發(fā)射(2)大炮有多大
CAEmitterCell就像是炮彈简珠,覺得了(1)初速度(2)加速度(3)炮彈類型(4)發(fā)射后的角度 等等
首先提醒CAEmitterLayer本身沒有什么難度阶界,主要在于兩點(diǎn):
- 屬性較多(一會會把屬性都列舉出來,不知道了隨時查閱就是)
- 調(diào)參數(shù)比較費(fèi)時(想要有好的動畫效果還得慢慢的去調(diào)整各項(xiàng)參數(shù)北救,不過沒有難度就是有點(diǎn)費(fèi)時間)
下面先認(rèn)識一下CAEmitterLayer(大炮)的屬性
/* The center of the emission shape. Defaults to (0, 0, 0). Animatable. */
發(fā)射源位置荐操。注意,是一個空間坐標(biāo)。并且標(biāo)記為 Animatable. 也就是說可以用 CoreAnimation 移動發(fā)射源位置
@property CGPoint emitterPosition;
@property CGFloat emitterZPosition;
“/* The size of the emission shape. Defaults to (0, 0, 0). Animatable.
* Depending on the `emitterShape' property some of the values may be
* ignored. */
發(fā)射源大小胳嘲。注意除了寬和高之外蜂桶,還有縱向深度。
文檔中還提到床嫌,這兩個屬性有時候可能會因?yàn)樵O(shè)置了 emitterShape 而被忽略护锤,具體情況實(shí)際嘗試一下就可以了送丰。
@property CGSize emitterSize;
@property CGFloat emitterDepth;
“/* A string defining the type of emission shape used. Current options are:
* `point' (the default), `line', `rectangle', `circle', `cuboid' and
* `sphere'. */
CA_EXTERN NSString * const kCAEmitterLayerPoint
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerLine
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerRectangle
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerCuboid
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerCircle
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerSphere
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
emitterShape 決定了發(fā)射源的形狀蹭劈。
@property(copy) NSString *emitterShape;
/* A string defining how particles are created relative to the emission
* shape. Current options are `points', `outline', `surface' and
* `volume' (the default). */
CA_EXTERN NSString * const kCAEmitterLayerPoints
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerOutline
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerSurface
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
CA_EXTERN NSString * const kCAEmitterLayerVolume
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_5_0);
emitterMode 決定了發(fā)射源的發(fā)射模式疗绣。
@property(copy) NSString *emitterMode;
平常用的多的比如 emitterShape 的 kCAEmitterLayerLine 和 kCAEmitterLayerPoint。這兩個從視覺上還是比較好區(qū)分的铺韧,這決定了你的粒子是從一個點(diǎn)「噴」出來的多矮,還是從一條線上每個點(diǎn)「噴」下來,前者像焰火哈打,后者像瀑布塔逃。顯然,下雪的效果更像后者料仗。
emitterMode 的 kCAEmitterLayerOutline 表示向外圍擴(kuò)散湾盗,如果你的發(fā)射源形狀是 circle,那么 kCAEmitterLayerOutline 就會以一個圓的方式向外擴(kuò)散開立轧。
又比如你想表達(dá)一股蒸汽向上噴的效果格粪,就可以設(shè)置 emitterShape 為 kCAEmitterLayerLine , emitterMode 為 kCAEmitterLayerOutline氛改。
CAEmitterCell(炮彈)的屬性
其實(shí)CAEmitterCell真是的名字叫粒子帐萎,下面詳細(xì)的介紹了CAEmitterCell的屬性,只要求大家屬性一下胜卤,以后用到了可以再來查閱疆导。
@property float birthRate; //每秒生成多少個粒子
@property float lifetime; //粒子存活的時間,以秒為單位
@property float lifetimeRange; // 可以為這個粒子存活的時間再指定一個范圍。
上面兩個屬性如果只用了lifetime那么粒子的存活時間就是固定的瑰艘,比如lifetime=10,那么粒子10s秒后就消失了是鬼。
如果使用了lifetimeRange,比如lifetimeRange=5紫新,那么粒子的存活時間就是在5s~15s這個范圍內(nèi)消失均蜜。
@property CGFloat velocity;//粒子平均初始速度。正數(shù)表示豎直向上芒率,負(fù)數(shù)豎直向下囤耳。
@property CGFloat velocityRange; //可以再指定一個范圍。
上面兩個屬性同lifetime和lifetimeRange
@property CGFloat xAcceleration;
@property CGFloat yAcceleration;
@property CGFloat zAcceleration; //三者構(gòu)成了一個空間矢量偶芍。決定了每個方向上粒子的加速度充择。
@property CGFloat emissionRange; //以錐形分布開的發(fā)射角度。角度用弧度制匪蟀。粒子均勻分布在這個錐形范圍內(nèi)椎麦。
@property CGFloat spin;//粒子的平均旋轉(zhuǎn)速度
@property CGFloat spinRange; //可指定一個范圍〔谋耄弧度制观挎。
@property(strong) id contents; //cell的內(nèi)容琴儿。通常是一個指針CGImageRef。
@property CGColorRef color; //可以把圖片「染」成你想要的顏色嘁捷。
@property(copy) NSString *name; //The name of the cell造成,用于構(gòu)建key paths。這也是后面手動控制動畫開始和結(jié)束的關(guān)鍵雄嚣。
好接下來我們舉個小例子晒屎,不懂得屬性可以去上面查閱
//創(chuàng)建一個CAEmitterLayer
CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
//指定發(fā)射源的位置
snowEmitter.emitterPosition = CGPointMake(self.view.bounds.size.width / 2.0, -10);
//指定發(fā)射源的大小
snowEmitter.emitterSize = CGSizeMake(self.view.bounds.size.width, 0.0);
//指定發(fā)射源的形狀 和 模式
snowEmitter.emitterShape = kCAEmitterLayerLine;
snowEmitter.emitterMode = kCAEmitterLayerOutline;
//創(chuàng)建CAEmitterCell
CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
//每秒多少個
snowflake.birthRate = 3.0;
//存活時間
snowflake.lifetime = 50.0;
//初速度
snowflake.velocity = 10;//因?yàn)閯赢媽儆诼潴w效果,所以我們只需要設(shè)置它在 y 方向上的加速度就行了缓升。
//初速度范圍
snowflake.velocityRange = 5;
//y方向的加速度
snowflake.yAcceleration = 2;
//
snowflake.emissionRange = 0;
snowflake.contents = (id) [[UIImage imageNamed:@"037"] CGImage];
//縮小
snowflake.scale = 0.5;
snowEmitter.emitterCells = [NSArray arrayWithObject:snowflake];
這樣這個動畫就完成了是不是很簡單鼓鲁,QQ里一些表情從天而降也是這個原理,有興趣的同學(xué)可以研究一下
接下來我們要回到文章一開始的那個動畫仔沿,這個動畫和上面的例子的最大的區(qū)別就是手動控制了動畫的開始和結(jié)束
接下來我們需要手動控制動畫的開始和結(jié)束坐桩。還記得前面提到的 @property(copy) NSString *name; 嗎?想要手動控制動畫的開始和結(jié)束封锉,我們必須通過 KVC 的方式設(shè)置 cell 的值才行绵跷。
開始
//CAEmitterLayer 根據(jù)自己的 emitterCells 屬性找到名叫 explosion 的 cell,
//并設(shè)置它的 birthRate 為 500成福。從而間接地控制了動畫的開始碾局。
[self.explosionLayer setValue:@500 forKeyPath:@"emitterCells.explosion.birthRate"];
結(jié)束
[self.explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosion.birthRate"];
具體代碼放在了GitHub上大家可以下載。
如果感覺這篇文章對您有所幫助奴艾,順手點(diǎn)個喜歡净当,謝謝啦