CAEmitterLayer 看上去像是許多 CAEmitterCell 的容器,這些 CAEmitterCell 定義了一個例子效果。你將會為不同的例子效果定義一個或多個 CAEmitterCell 作為模版,同時 CAEmitterLayer 負責基于這些模版實例化一個粒子流。一個 CAEmitterCell 類似于一個 CALayer :它有一個 contents 屬性可以定義為一個 CGImage ,另外還有一些可設置屬性控制著表現和行為。
以上解釋來源于網絡
我來舉個通俗易懂的例子吧CAEmitterLayer就像大炮,決定了(1)哪里發射(2)大炮有多大
CAEmitterCell就像是炮彈,覺得了(1)初速度(2)加速度(3)炮彈類型(4)發射后的角度 等等
首先提醒CAEmitterLayer本身沒有什么難度,主要在于兩點:
屬性較多(一會會把屬性都列舉出來,不知道了隨時查閱就是)
調參數比較費時(想要有好的動畫效果還得慢慢的去調整各項參數,不過沒有難度就是有點費時間)
CAEmitterLayer(大炮)的屬性
/* The center of the emission shape. Defaults to (0, 0, 0). Animatable. */發射源位置。注意,是一個空間坐標。并且標記為 Animatable. 也就是說可以用 CoreAnimation 移動發射源位置
@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. */
發射源大小。注意除了寬和高之外,還有縱向深度。
文檔中還提到,這兩個屬性有時候可能會因為設置了 emitterShape 而被忽略,具體情況實際嘗試一下就可以了。
@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 決定了發射源的形狀。
@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 決定了發射源的發射模式。
@property(copy) NSString *emitterMode;
平常用的多的比如 emitterShape 的 kCAEmitterLayerLine 和 kCAEmitterLayerPoint。這兩個從視覺上還是比較好區分的,這決定了你的粒子是從一個點「噴」出來的,還是從一條線上每個點「噴」下來,前者像焰火,后者像瀑布。顯然,下雪的效果更像后者。
emitterMode 的 kCAEmitterLayerOutline 表示向外圍擴散,如果你的發射源形狀是 circle,那么 kCAEmitterLayerOutline 就會以一個圓的方式向外擴散開。
又比如你想表達一股蒸汽向上噴的效果,就可以設置 emitterShape 為 kCAEmitterLayerLine , emitterMode 為 kCAEmitterLayerOutline。
CAEmitterCell(炮彈)的屬性
其實CAEmitterCell真是的名字叫粒子,下面詳細的介紹了CAEmitterCell的屬性,只要求大家屬性一下,以后用到了可以再來查閱。
@property float birthRate; //每秒生成多少個粒子
@property float lifetime; //粒子存活的時間,以秒為單位
@property float lifetimeRange; // 可以為這個粒子存活的時間再指定一個范圍。
上面兩個屬性如果只用了lifetime那么粒子的存活時間就是固定的,比如lifetime=10,那么粒子10s秒后就消失了。
如果使用了lifetimeRange,比如lifetimeRange=5,那么粒子的存活時間就是在5s~15s這個范圍內消失。
@property CGFloat velocity;//粒子平均初始速度。正數表示豎直向上,負數豎直向下。
@property CGFloat velocityRange; //可以再指定一個范圍。
上面兩個屬性同lifetime和lifetimeRange
@property CGFloat xAcceleration;
@property CGFloat yAcceleration;
@property CGFloat zAcceleration; //三者構成了一個空間矢量。決定了每個方向上粒子的加速度。
@property CGFloat emissionRange; //以錐形分布開的發射角度。角度用弧度制。粒子均勻分布在這個錐形范圍內。
@property CGFloat spin;//粒子的平均旋轉速度
@property CGFloat spinRange; //可指定一個范圍。弧度制。
@property(strong) id contents; //cell的內容。通常是一個指針CGImageRef。
@property CGColorRef color; //可以把圖片「染」成你想要的顏色。
@property(copy) NSString *name; //The name of the cell,用于構建key paths。這也是后面手動控制動畫開始和結束的關鍵。
好接下來我們舉個小例子,
//創建一個CAEmitterLayer
CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
//指定發射源的位置
snowEmitter.emitterPosition = CGPointMake(self.view.bounds.size.width / 2.0, -10);
//指定發射源的大小
snowEmitter.emitterSize? = CGSizeMake(self.view.bounds.size.width, 0.0);
//指定發射源的形狀 和 模式
snowEmitter.emitterShape = kCAEmitterLayerLine;
snowEmitter.emitterMode? = kCAEmitterLayerOutline;
//創建CAEmitterCell
CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
//每秒多少個
snowflake.birthRate = 3.0;
//存活時間
snowflake.lifetime = 50.0;
//初速度
snowflake.velocity = 10;//因為動畫屬于落體效果,所以我們只需要設置它在 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];
接下來我們需要手動控制動畫的開始和結束。還記得前面提到的 @property(copy) NSString *name; 嗎?想要手動控制動畫的開始和結束,我們必須通過 KVC 的方式設置 cell 的值才行。
開始
//CAEmitterLayer 根據自己的 emitterCells 屬性找到名叫 explosion 的 cell,
//并設置它的 birthRate 為 500。從而間接地控制了動畫的開始。
[self.explosionLayer setValue:@500 forKeyPath:@"emitterCells.explosion.birthRate"];
- (void)startFire{
// 每秒噴射的80個
[self.emitterLayer setValue:@1000 forKeyPath:@"emitterCells.explosion.birthRate"];
// 開始
self.emitterLayer.beginTime = CACurrentMediaTime();
// 執行停止
[self performSelector:@selector(stopFire) withObject:nil afterDelay:0.1];
}
結束
[self.explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosion.birthRate"];
- (void)stopFire {
//每秒噴射的個數0個 就意味著關閉了
[self.emitterLayer setValue:@0 forKeyPath:@"emitterCells.explosion.birthRate"];
}