關於CAEmitterLayer和CAEmitterCell結合使用

weixin_34321977發表於2017-07-31

今天我們來看下CAEmitterLayer(粒子發生器)在開發中的使用

一、CAEmitterLayer 粒子發生器

1、CAEmitterLayer是CALayer的一個子類,和CAEmitterCell一起使用可以創造出多樣的動畫效果。

2、CAEmitterLayer主要用於實現基於Core Animation的粒子發生器系統。

3、在粒子系統中,CAEmitterLayer負責發射粒子(當然粒子也可以發射粒子),而這些所謂的粒子,就是CAEmitterCell,我們可以將CAEmitterLayer比作是CAEmitterCell的容器,它會按照你的設定來以不同的樣式不斷產生粒子,也就是CAEmitterCell。

4、CAEmitterLayer決定了粒子從什麼樣的幾何特性上發射出來,這個幾何特性包括了位置,形狀,大小。另外還有一些渲染相關的特性。另外的一些屬性是CAEmitterLayer和CAEmiiterCell都有的,CAEmitterLayer的這些屬性會作為CAEmitterCell相同屬性的係數。

例如當CAEmitterCell的lifetime(生命週期)為2,其所屬CAEmitterLayer的lifetime為3時,在其它引數選擇預設值的情況下,這個CAEmitterCell的生命週期就是2*3=6秒,6秒後,CAEmitterCell就會從粒子系統中被移除。

5、CAEmitterCell則決定了粒子自身的一些特徵,例如速度,加速度,發射的範圍,顏色等等。這些屬性大多是以“中間值”配合一個範圍值的方式來表示的。

例如velocity和velocityRange。表示CAEmitterCell的初始速度為velocity ± velocityRange。

二、CAEmitterLayer的屬性

CAEmitterLayer類提供了一個粒子發射器系統為核心的動畫。這些粒子是由CAEmitterCell組成的例項,它相當於一個管理者,來管理 CAEmitterCell的發射的一些細節,比如發射的位置,發射形狀等等。

/* 

@interface CAEmitterLayer : CALayer 

 --粒子的陣列 把設定好的粒子放入陣列設定到layer上

 @property(nullable, copy) NSArray*emitterCells;

--粒子產生係數,預設1.0;每個cell的產生率乘以這個粒子產生係數,得出每一秒粒子的建立個數。 即:cell.birthRate 乘以 layer.birthRate =每秒粒子產生個數

@property float birthRate;

--粒子的生命週期係數,預設1.0  即:(cell.lifetime 乘以 layer.lifetime)等於粒子的生命週期

@property float lifetime;

--發射源中心點的位置 預設(0,0)

@property CGPoint emitterPosition;

--z軸上的位置

@property CGFloat emitterZPosition;

--是發射源的大小 並不是layer的大小

@property CGSize emitterSize;

--

@property CGFloat emitterDepth;

--發射源的形狀 有圓形 方形 線型等 粒子從什麼形狀發射出來,它並不是表示粒子自己的形狀。

kCAEmitterLayerPoints 點模式,發射器是以點的形勢發射粒子。

kCAEmitterLayerOutline 輪廓,即邊上 整個邊框都是發射點,即邊框進行發射

kCAEmitterLayerSurface 區域進行拋灑

kCAEmitterLayerVolume 容積,即3D圖形的體積內

@property(copy) NSString *emitterShape;

--發散形式 

kCAEmitterLayerPoint 點形狀,發射源的形狀就是一個點,

kCAEmitterLayerLine 線形狀,發射源的形狀是一條線,位置在rect的橫向的位於垂直方向中間那條

kCAEmitterLayerRectangle 矩形狀,發射源是一個矩形,

kCAEmitterLayerCuboid 立體矩形形狀,發射源是一個立體矩形,這裡要生效的話需要設定z方向的資料,如果不設定就同矩形狀

kCAEmitterLayerCircle 圓形形狀,發射源是一個圓形,形狀為矩形包裹的那個圓,二維的

kCAEmitterLayerSphere 立體圓形,三維的圓形,同樣需要設定z方向資料,不設定則通二維一樣

@property(copy) NSString *emitterMode;

--描繪模式 

 kCAEmitterLayerUnordered 粒子是無序出現的,多個發射源將混合
 
 kCAEmitterLayerOldestFirst 宣告久的粒子會被渲染在最上層
 
 kCAEmitterLayerOldestLast 年輕的粒子會被渲染在最上層
 
 kCAEmitterLayerBackToFront 粒子的渲染按照Z軸的前後順序進行
 
 kCAEmitterLayerAdditive 進行粒子混合

@property(copy) NSString *renderMode;

--是否展示在z軸上的效果 把圖層進行3d變形如沿y軸旋轉90度 會有很明顯的立體效果

@property BOOL preservesDepth;

--粒子速度係數, 預設1.0 發射速度 和cell的速度屬性一起決定了粒子的速度 猜測粒子的速度是兩者的乘積

而且和cell的速度屬性不同 這個屬性可以為負 (cell.velocity 乘以 layer.velocity)等於粒子的速度

為負的時候發散方向是向反方向的 為正時是向指定方向的

@property float velocity;

--粒子的縮放比例係數, 預設1.0 縮放大小 和速度相同 粒子的scale值是兩者相乘 cell.scale 乘以 layer.scale)等於粒子的縮放比例

@property float scale;

-- 自旋轉速度係數, 預設1.0 cell.spin 乘以 layer.spin)等於粒子的自旋轉速度

@property float spin;

-- 隨機數設定種子

@property unsigned int seed;

*/

三、CAEmitterCell部分屬性

CAEmitterCell是粒子發射系統裡的粒子,用CAEmitterCell來定義你所需要的粒子的樣式,圖片,顏色,方向,運動,縮放比例和生命週期等等。

/*

@interface CAEmitterCell : NSObject

--粒子的建立

+ (instancetype)emitterCell;

--根據鍵獲得值

+ (nullable id)defaultValueForKey:(NSString *)key

--是否歸檔鍵值

- (BOOL)shouldArchiveValueForKey:(NSString *)key;

--粒子的名字,預設nil.

@property(nullable, copy) NSString *name;

--是否允許被繪製出來

@property(getter=isEnabled) BOOL enabled;

--生成速率預設0

@property float birthRate;

--生存週期以秒為單位。兩者預設0

@property float lifetime;

--生存週期的絕對值的偏移量的最大值

@property float lifetimeRange;

--z軸方向上的發射角度緯度,緯度角代表了x-z軸平面上與x軸之間的夾角,兩者預設0

@property CGFloat emissionLatitude;

--在xy平面上的發射角度經度,經度角代表了x-y軸平面上與x軸之間的夾角

@property CGFloat emissionLongitude;

--周圍發射角度,預設0

@property CGFloat emissionRange;

--放射速度兩者預設0

@property CGFloat velocity;

--速度偏移量

@property CGFloat velocityRange;

--在三個座標軸上的速度增量可以做出類似重力風吹的效果預設0

@property CGFloat xAcceleration;

@property CGFloat yAcceleration;

@property CGFloat zAcceleration;

--縮放數值

@property CGFloat scale;

--縮放數值的偏移量

@property CGFloat scaleRange;

--縮放速度不清楚怎麼設定可能和velocity屬性有關係

@property CGFloat scaleSpeed;

--旋轉

@property CGFloat spin;

--旋轉的偏移量

@property CGFloat spinRange;

--設定cell的顏色content的顏色會影響實際顏色預設白色

@property(nullable) CGColorRef color;

--設定三原色和透明度的值偏移值0-1

@property float redRange;

@property float greenRange;

@property float blueRange;

@property float alphaRange;

--變色速率

@property float redSpeed;

@property float greenSpeed;

@property float blueSpeed;

@property float alphaSpeed;

--cell的內容一般是UIImage

@property(nullable, strong) id contents;

--內容範圍預設(0,0,1,1)

@property CGRect contentsRect;

--內容縮放

@property CGFloat contentsScale;

--渲染'內容'影象時使用的濾波器引數。

@property(copy) NSString *minificationFilter;

@property(copy) NSString *magnificationFilter;

@property float minificationFilterBias;

---粒子發射的粒子

@property(nullable, copy) NSArray *emitterCells;

@property(nullable, copy) NSDictionary *style;

*/

總結,我們可以emitterShape和emitterMode組合多種需要的效果圖。

四、相關例項

1、仿造微信掉落表情效果圖:

1704370-6a4c705f5efc9b14.gif
snow.gif

程式碼:

- (void)snowAnimation

{

CAEmitterLayer *snowEmitter  = [CAEmitterLayer layer];

//降落區域的方位

snowEmitter.frame = self.view.bounds;

//新增到父檢視Layer上

[self.view.layer addSublayer:snowEmitter];

//指定發射源的位置

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;

snowEmitter.renderMode = kCAEmitterLayerOldestFirst;

//建立CAEmitterCell

CAEmitterCell *snowflake = [CAEmitterCell emitterCell];

//每秒多少個

snowflake.birthRate = 10.0;

//存活時間

snowflake.lifetime = 50.0;

//初速度,因為動畫屬於落體效果,所以我們只需要設定它在y方向上的加速度就行了。

snowflake.velocity = 10;

//初速度範圍

snowflake.velocityRange = 5;

//y軸方向的加速度

snowflake.yAcceleration = 30;

//以錐形分佈開的發射角度。角度用弧度制。粒子均勻分佈在這個錐形範圍內。

snowflake.emissionRange = 5;

//設定降落的圖片

snowflake.contents  = (id) [[UIImage imageNamed:@"love"] CGImage];

//圖片縮放比例

snowflake.scale = 0.5;

//開始動畫

snowEmitter.emitterCells = [NSArray arrayWithObject:snowflake];

}

2、煙花效果圖

1704370-094c600f9b6e065a.gif
yanhua.gif

程式碼:

- (void)fireWorkAnimation{
    _emitterLayer = [CAEmitterLayer layer];
    //發射源
    _emitterLayer.emitterPosition = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height - 50);
    //發射源尺寸大小
    _emitterLayer.emitterSize = CGSizeMake(50, 0);
    //發射源模式
    _emitterLayer.emitterMode = kCAEmitterLayerOutline;
    //發射源形狀
    _emitterLayer.emitterShape = kCAEmitterLayerLine;
    //渲染模式
    _emitterLayer.renderMode = kCAEmitterLayerAdditive;
    
    //發射方向
    _emitterLayer.velocity = 1;
    
    //產生粒子數量
    _emitterLayer.seed = (arc4random() % 100 ) + 1;
    
    
    CAEmitterCell *cell = [CAEmitterCell emitterCell];
    
    //產生的速lv
    cell.birthRate = 1.0;
    //發射角度
    cell.emissionRange = 0.11 * M_PI;
    //速度
    cell.velocity = 300;
    //範圍
    cell.velocityRange = 150;
    //y 加速度
    cell.yAcceleration = 75;
    //存活時間
    cell.lifetime = 2.04;
    //cell 內容
    cell.contents = (__bridge id _Nullable)([UIImage imageNamed:@"FFRing"].CGImage);
    //縮放比例
    cell.scale = 0.2;
    //粒子顏色
    cell.color = [[UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0] CGColor];
    
    // 一個粒子的顏色green 能改變的範圍
    cell.greenRange                 = 1.0;
    // 一個粒子的顏色red 能改變的範圍
    cell.redRange                   = 1.0;
    // 一個粒子的顏色blue 能改變的範圍
    cell.blueRange                  = 1.0;
    // 子旋轉角度範圍
    cell.spinRange                  = M_PI;
    
    // 爆炸
    CAEmitterCell *burst            = [CAEmitterCell emitterCell];
    // 粒子產生係數
    burst.birthRate                 = 1.0;
    // 速度
    burst.velocity                  = 0;
    // 縮放比例
    burst.scale                     = 2.5;
    // shifting粒子red在生命週期內的改變速度
    burst.redSpeed                  = -1.5;
    // shifting粒子blue在生命週期內的改變速度
    burst.blueSpeed                 = +1.5;
    // shifting粒子green在生命週期內的改變速度
    burst.greenSpeed                = +1.0;
    //生命週期
    burst.lifetime                  = 0.35;
    
    
    // 火花 and finally, the sparks
    CAEmitterCell *spark            = [CAEmitterCell emitterCell];
    //粒子產生係數,預設為1.0
    spark.birthRate                 = 400;
    //速度
    spark.velocity                  = 125;
    // 360 deg//周圍發射角度
    spark.emissionRange             = 2 * M_PI;
    // gravity//y方向上的加速度分量
    spark.yAcceleration             = 75;
    //粒子生命週期
    spark.lifetime                  = 3;
    //是個CGImageRef的物件,既粒子要展現的圖片
    spark.contents                  = (id)
    [[UIImage imageNamed:@"FFTspark"] CGImage];
    //縮放比例速度
    spark.scaleSpeed                = -0.2;
    //粒子green在生命週期內的改變速度
    spark.greenSpeed                = -0.1;
    //粒子red在生命週期內的改變速度
    spark.redSpeed                  = 0.4;
    //粒子blue在生命週期內的改變速度
    spark.blueSpeed                 = -0.1;
    //粒子透明度在生命週期內的改變速度
    spark.alphaSpeed                = -0.25;
    //子旋轉角度
    spark.spin                      = 2* M_PI;
    //子旋轉角度範圍
    spark.spinRange                 = 2* M_PI;
    
    
    self.emitterLayer.emitterCells = [NSArray arrayWithObject:cell];
    cell.emitterCells = [NSArray arrayWithObjects:burst, nil];
    burst.emitterCells = [NSArray arrayWithObject:spark];
    [self.view.layer addSublayer:self.emitterLayer];
}

demo: Github

相關文章