iOS動畫之用CAEmitterLayer實(shí)現(xiàn)炫酷的動畫

CAEmitterLayer.gif

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)鍵雄嚣。



好接下來我們舉個小例子晒屎,不懂得屬性可以去上面查閱
1.gif
    //創(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)個喜歡净当,謝謝啦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蕴潦,隨后出現(xiàn)的幾起案子像啼,更是在濱河造成了極大的恐慌,老刑警劉巖潭苞,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忽冻,死亡現(xiàn)場離奇詭異,居然都是意外死亡此疹,警方通過查閱死者的電腦和手機(jī)僧诚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝗碎,“玉大人湖笨,你說我怎么就攤上這事”钠铮” “怎么了慈省?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眠菇。 經(jīng)常有香客問我辫呻,道長清钥,這世上最難降的妖魔是什么琼锋? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任放闺,我火速辦了婚禮,結(jié)果婚禮上缕坎,老公的妹妹穿的比我還像新娘怖侦。我一直安慰自己,他們只是感情好谜叹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布匾寝。 她就那樣靜靜地躺著,像睡著了一般荷腊。 火紅的嫁衣襯著肌膚如雪艳悔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天女仰,我揣著相機(jī)與錄音猜年,去河邊找鬼。 笑死疾忍,一個胖子當(dāng)著我的面吹牛乔外,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播一罩,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼杨幼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聂渊?” 一聲冷哼從身側(cè)響起差购,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汉嗽,沒想到半個月后欲逃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暖夭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了撵孤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迈着。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖邪码,靈堂內(nèi)的尸體忽然破棺而出裕菠,到底是詐尸還是另有隱情,我是刑警寧澤闭专,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布奴潘,位于F島的核電站旧烧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏画髓。R本人自食惡果不足惜掘剪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奈虾。 院中可真熱鬧夺谁,春花似錦、人聲如沸肉微。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碉纳。三九已至勿负,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劳曹,已是汗流浹背奴愉。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厚者,地道東北人躁劣。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像库菲,于是被迫代替她去往敵國和親账忘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容