本期內容:
- CAEmitterLayer 粒子發射器(層)
- CAEmitterCell 粒子
- 下雨效果
- 下雪效果
- 煙火效果
- 需要注意的屬性疊加
- 總結以及demo下載
CAEmitterLayer 粒子發射器(層)
簡介:CAEmitterLayer是發射、動畫和渲染粒子系統的層。 是CALayer的一個常用子類,CALayer的子類有很多,如果能很好的使用它們會得到一些意想不到的效果。CAEmitterLayer就是其中之一,CAEmitterLayer是用於實現基於Core Animation的粒子發生器系統。由CAEmitterCell實例定義的粒子被繪製在層的背景顏色和邊框之上。
具體屬性清單:
// 常用屬性:
NSArray<CAEmitterCell *> *emitterCells; // 用來裝粒子的數組
CGPoint emitterPosition; // 決定了粒子發射形狀的中心點
CGFloat emitterZPosition;
CGSize emitterSize; // 發射源的尺寸大小
NSString *emitterShape; // 發射源的形狀
NSString *emitterMode; // 發射模式
NSString *renderMode; // 渲染模式
// 不常用屬性:
float birthRate; // 粒子產生係數,默認1.0 (可以在Cell裏面賦值)
float lifetime; // 粒子的生命週期係數, 默認1.0 (可以在Cell裏面賦值)
BOOL preservesDepth; // 定義該層是否將其子層壓平到其平面。
CGFloat emitterDepth; // 確定發射器形狀的深度
float velocity; // 粒子速度係數, 默認1.0 (可以在Cell裏面賦值)
float scale; // 粒子的縮放比例係數, 默認1.0 (可以在Cell裏面賦值)
float spin; // 粒子的自旋轉速度係數, 默認1.0 (可以在Cell裏面賦值)
unsigned int seed; // 隨機數發生器
CAEmitterLayer的使用方式如下:
// 1.創建CAEmitterLayer
emitterLayer = [CAEmitterLayer layer];
// 2.設置CAEmitterLayer的屬性(最主要的是前四個)
// 發射源的形狀 是枚舉類型
emitterLayer.emitterShape = kCAEmitterLayerLine;
// kCAEmitterLayerCircle
// 粒子從一個以(發射位置)爲中心的圓中發射出來。
// kCAEmitterLayerCuboid
// 粒子從一個相反角的長方體(3D矩形)發射。
// kCAEmitterLayerLine
// 粒子從(發射位置)沿直線發射。
// kCAEmitterLayerPoint
// 粒子從一個點(發射位置)發射出來。
// kCAEmitterLayerRectangle
// 粒子從一個有相對角的矩形發射。
// kCAEmitterLayerSphere
// 粒子從一個以(發射位置)爲中心的球體中發射出來。
// 發射模式 枚舉類型
emitterLayer.emitterMode = kCAEmitterLayerSurface;
// kCAEmitterLayerOutline
// 粒子從粒子發射器的輪廓發射出來。
// kCAEmitterLayerPoints
// 粒子從粒子發射器上的點發射出來。
// kCAEmitterLayerSurface
// 粒子從粒子發射器的表面發射出來。
// kCAEmitterLayerVolume
// 粒子從粒子發射器中的a位置發射。
// 發射源的size 決定了發射源的大小,如果做了傾斜或者便宜屏幕寬度是不夠的,那時候就需要自定義
emitterLayer.emitterSize = self.view.frame.size;
// 發射源的位置
emitterLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
// 渲染模式 枚舉類型 (⭐️這個渲染模式表達效果會很不好,不常用,kCAEmitterLayerAdditive,可以讓重疊的部分高亮)
emitterLayer.renderMode = kCAEmitterLayerAdditive;
// kCAEmitterLayerOldestFirst;
// kCAEmitterLayerOldestLast;
// kCAEmitterLayerBackToFront;
// kCAEmitterLayerAdditive;
// 3.添加到目標視圖的layer上
[self.view.layer addSublayer:emitterLayer];
CAEmitterCell 粒子
簡介:CAEmitterCell類表示CAEmitterLayer對象發出的一個粒子源。 CAEmitterCell定義發射粒子的方向和性質。CAEmitterLayer發射器可以有一系列子粒子,這些子粒子可以讓粒子自己發射粒子,也就是CAEmitterCell也可以發射CAEmitterCell
/**
具體屬性清單:
// 常用屬性清單(以空行來劃分使用點):
NSString *name; // 粒子名字, 默認爲nil
float birthRate; // 粒子的產生率,默認0
float lifetime; // 粒子的生命週期,以秒爲單位。默認0
float lifetimeRange; // 粒子的生命週期的範圍,以秒爲單位。默認0
CGFloat emissionLatitude;// 指定緯度,緯度角代表了在x-z軸平面座標系中與x軸之間的夾角,默認0:
CGFloat emissionLongitude; // 指定經度,經度角代表了在x-y軸平面座標系中與x軸之間的夾角,默認0:
CGFloat emissionRange; //發射角度範圍,默認0,以錐形分佈開的發射角度。角度用弧度制。粒子均勻分佈在這個錐形範圍內;
CGFloat velocity; // 速度和速度範圍,兩者默認0
CGFloat velocityRange;
CGFloat xAcceleration; // x,y,z方向上的加速度分量,三者默認都是0
CGFloat yAcceleration;
CGFloat zAcceleration;
CGFloat scale; // 縮放比例, 默認是1
CGFloat scaleRange; // 縮放比例範圍,默認是0
CGFloat scaleSpeed; // 在生命週期內的縮放速度,默認是0
CGFloat spin; // 粒子的平均旋轉速度,默認是0
CGFloat spinRange; // 自旋轉角度範圍,弧度制,默認是0
CGColorRef color; // 粒子的顏色,默認白色
float redRange; // 粒子顏色red,green,blue,alpha能改變的範圍,默認0
float greenRange;
float blueRange;
float alphaRange;
float redSpeed; // 粒子顏色red,green,blue,alpha在生命週期內的改變速度,默認都是0
float greenSpeed;
float blueSpeed;
float alphaSpeed;
id contents; // 粒子的內容,爲CGImageRef的對象
NSArray<CAEmitterCell *> *emitterCells; // 粒子裏面的粒子
// 非常不常用屬性:
BOOL enabled;
NSDictionary *style;
CGRect contentsRect;
CGFloat contentsScale;
NSString *minificationFilter;
NSString *magnificationFilter;
float minificationFilterBias;
*/
CAEmitterCell的使用方式如下:
// 1. 配置cell
CAEmitterCell * showCell = [CAEmitterCell emitterCell];
// 2. 設置屬性
showCell.contents = (id)[[UIImage imageNamed:@"xxx"] CGImage]; // 粒子的內容 是CGImageRef類型的
// 粒子的產生率
showCell.birthRate = 25.f;
// 粒子的生命週期,以秒爲單位。
showCell.lifetime = 100.f;
// 粒子的生命週期的範圍,以秒爲單位。默認0
showCell.lifetimeRange = 25.f;
// 速度,制約粒子生命週期
// 官方解釋爲:指定時間如何從父時間空間映射到接收者的時間空間。「必需的」
// 值越大粒子消失的越快
showCell.speed = 2.f;
// 速度
showCell.velocity = 20.f;
// 速度範圍
showCell.velocityRange = 80.f;
// 三軸加速度(一般使用Y值)
showCell.yAcceleration = 90.f;
// showCell.xAcceleration = 20.f;
// showCell.zAcceleration = 10.f;
// 縮放比列
showCell.scale = 0.3;
// 縮放範圍
showCell.scaleRange = 0.5;
// 在粒子的生命週期內尺度變化的速度。可以做成動畫。
showCell.scaleSpeed = 0.02;
// 設置經緯度(方向)(⭐️⭐️需要在 kCAEmitterLayerPoint 的情況下搭配使用)
// showCell.emissionLongitude = M_PI; // 上(-M_PI_2) 下(M_PI_2) 左(M_PI) 右(M_PI_4) 通常使用這個
// // showCell.emissionLatitude = -M_PI_2; // 前(-M_PI_2) 後(M_PI_2) 左(M_PI) 右(M_PI_4)
// // 設置角度,控制發射範圍(受到經緯度的影響)
// showCell.emissionRange = M_PI / 6; // 圍繞X軸向左90度
// 設置自轉速度
showCell.spin = 0.f;
// 設置自轉方向
showCell.spinRange = M_PI;
// 設置顏色(⭐️⭐️直接影響到圖片的原有顏色)
// snowCell.color = [[UIColor colorWithRed:0.5 green:0.f blue:0.5 alpha:1.f] CGColor];
// 粒子在三個色相中以及可見度的變化程度
showCell.redRange = 10.f;
showCell.greenRange = 20.f;
showCell.blueRange = 30.f;
showCell.redSpeed = 1.f;
showCell.greenSpeed = 1.f;
showCell.blueSpeed = 1.f;
showCell.alphaRange = 0.8;
showCell.alphaSpeed = -0.1f;
// 3.粒子添加到CAEmitterLayer上
emitterLayer.emitterCells = @[showCell];
看着代碼很煩人是吧?把我們上面的 emitterLayer 和 showCell 結合在一起,就是一個完整的粒子發射過程了,給大家看看效果:
其實實現的效果非常簡單,但一定要自己去嘗試上面👆代碼中,那些註釋了的東西。
下雨效果
接下來繼續,下雨效果,大家來想想下雨效果是什麼樣子呢?粒子應該從什麼位置發射?應該怎麼配置?
思考結束,我們繼續:
// 創建粒子發射器圖層
CAEmitterLayer * rainEmitterLayer = [CAEmitterLayer layer];
// 設置屬性
// 發射源的形狀 是枚舉類型 ⭐️因爲是下雨 所以要作爲 直線發射
rainEmitterLayer.emitterShape = kCAEmitterLayerLine;
// 發射模式 從表面發射
rainEmitterLayer.emitterMode = kCAEmitterLayerSurface;
// 發射源的size 據定了發射源的大小 設定發射器大小爲整個屏幕的大小
rainEmitterLayer.emitterSize = self.view.frame.size;
// 發射源的位置 ⭐️因爲是下雨 所以要從屏幕上方往下發射(如果想讓粒子佔據整個屏幕的寬度,設定位置寬度爲視圖的一半)
rainEmitterLayer.emitterPosition = CGPointMake(self.view.frame.size.width*0.5, -20);
// 渲染模式,暫不使用 ⭐️很不常用
// 添加到目標視圖的layer上
[self.view.layer addSublayer:rainEmitterLayer];
// 配置粒子Cell
CAEmitterCell * rainCell = [CAEmitterCell emitterCell];
// 設置粒子圖片
rainCell.contents = (id)[[UIImage imageNamed:@"rain"]CGImage];
// 可以以分組的形式來記憶粒子的設定如下:
// 組1 ⭐️三個參數缺一不可
// 設置粒子產生率 每秒 60個 ⭐️粒子產生率可以通過 EmitterLayer 來控制
rainCell.birthRate = 60.f;
// 設置粒子生命週期 生命週期 40秒
rainCell.lifetime = 40.f;
// 設置粒子持續時間,持續時間制約粒子生命週期
rainCell.speed = 5.f;
// 組2
// 設置粒子速度
rainCell.velocity = 20.f;
// 設置粒子速度範圍
rainCell.velocityRange = 100.f;
// 設置粒子下落加速度 Y軸
rainCell.yAcceleration = 2000.f;
// 組3 雨圖片需要縮放統一大小 不能使用範圍
// 設置縮放比例
rainCell.scale = 0.05f;
// // 設置縮放範圍
// rainCell.scaleRange = 0.8f;
// // 設置粒子存在期間縮放變化的速度
// rainCell.scaleSpeed = 0.5f;
// // 組4 雨點不需要旋轉
// // 設置粒子旋轉速度
// rainCell.spin = 0.5f;
// // 設置粒子旋轉範圍
// rainCell.spinRange = M_PI_2;
// 設置粒子顏色 會附和圖片修改圖片顏色
rainCell.color = [[UIColor whiteColor]CGColor];
// 添加到粒子發射器
rainEmitterLayer.emitterCells = @[rainCell];
運行效果如下:
我們可以稍加改進,比如綿綿細雨,試想一下,怎麼才能做到往一個方向傾斜的呢?我們正常的加速度是:yAcceleration,用來設置粒子下落加速度(Y軸),如果想要傾斜,我們就加上xAcceleration,也就是X軸加速度。運行效果如下:
這時候新的問題來了,我們會發現,下雨覆蓋不滿屏幕了這是爲什麼呢?之前說了 EmitterLayer 設置屬性有:
①發射源的size 據定了發射源的大小 EmitterLayer.emitterSize 目前我們的size是屏幕寬度,即使我們把雨弄傾斜了,發射源的大小和下落位置的大小還是屏幕寬度,這時候我們就需要調整 EmitterLayer 的父 layer 的 View 的大小了,寬度變成 2 倍。
②發射源的位置 EmitterLayer.emitterPosition,之前我們學習到了如果想讓粒子佔據整個屏幕的寬度,設定位置寬度爲視圖的一半,這時候也同樣。
通過以上兩個步驟,傾斜的雨點就會沾滿整個屏幕了
下雪效果
好了,我們繼續來學習下雪效果,之前下雨效果已經完成了,下雪就很簡單啦,直接上代碼:
// 設置發射器圖層
CAEmitterLayer * snowEmitterlayer = [CAEmitterLayer layer];
// 發射源的形狀 是枚舉類型 ,因爲是下雨 所以要作爲 直線發射
snowEmitterlayer.emitterShape = kCAEmitterLayerLine;
// 發射模式
snowEmitterlayer.emitterMode = kCAEmitterLayerSurface;
// 發射源的size 據定了發射源的大小
snowEmitterlayer.emitterSize = self.view.frame.size;
// 發射源的位置 從屏幕上方往下發射
snowEmitterlayer.emitterPosition = CGPointMake(self.view.frame.size.width*0.5, -10);
// 渲染模式,暫不使用
[seslf.view.layer addSublayer:snowEmitterlayer];
// 創建粒子
CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
// 設置粒子圖片
snowCell.contents = (id)[[UIImage imageNamed:@"snow@3x"]CGImage];
// 組1
// 設置粒子產生率
snowCell.birthRate = 10.f;
// 設置粒子生命週期
snowCell.lifetime = 40.f;
// 設置粒子持續時間,持續時間制約粒子生命週期
snowCell.speed = 5.f;
// 組2
// 設置粒子速度
snowCell.velocity = 20.f;
// 設置粒子速度範圍
snowCell.velocityRange = 100.f;
// 設置粒子下落加速度 Y軸
snowCell.yAcceleration = 80.f;
// 組3 雪花圖片 需要縮放大小 使用縮放範圍
// 設置縮放比例
snowCell.scale = 0.2f;
// 設置縮放範圍
// snowCell.scaleRange = 0.5f;
// // 設置粒子存在期間縮放變化的速度
// snowCell.scaleSpeed = 0.5f;
// 組4 雨點不需要旋轉
// 設置粒子旋轉速度
// snowCell.spin = 0.5f;
// // 設置粒子旋轉範圍
// snowCell.spinRange = M_PI_2;
// 設置粒子顏色 會附和圖片修改圖片顏色
// snowCell.color = [[UIColor redColor]CGColor];
// 添加到粒子發射器
snowEmitterlayer.emitterCells = @[snowCell];
運行效果如圖:
開出來很單調是吧?我們來使用幾個屬性,讓下雪變得好看吧:
①設置粒子縮放範圍 snowCell.scaleRange
②設置粒子存在期間縮放變化的速度 snowCell.scaleSpeed
③設置粒子旋轉速度 snowCell.spin
④設置粒子旋轉範圍snowCell.spinRange
如果想設置大雪我們就增加Y軸加速度,圖片展示了以上兩個修改,運行效果如圖:
煙火效果
在上文的學習中,我們看到了CAEmitterCell的特性,即:CAEmitterCell也可以發射CAEmitterCell,現在就來給大傢俱體展示一下:
// 配置layer
CAEmitterLayer * fireworksLayer = [CAEmitterLayer layer];
[self.view.layer addSublayer:fireworksLayer];
// 發射源大小
fireworksLayer.emitterSize = CGSizeMake(self.view.layer.bounds.size.width * 0.1, 0.f);
// 發射位置 在底部向上發射
fireworksLayer.emitterPosition = CGPointMake(self.view.layer.bounds.size.width * 0.5, self.view.layer.bounds.size.height);
// 以直線發射
fireworksLayer.emitterShape = kCAEmitterLayerLine;
// 在指定位置的表面發射
fireworksLayer.emitterMode = kCAEmitterLayerSurface;
// 渲染效果,疊加高亮
fireworksLayer.renderMode = kCAEmitterLayerAdditive;
// 發射粒子效果
CAEmitterCell * shootCell = [CAEmitterCell emitterCell];
shootCell.name = @"shootCell";
// 粒子產生率 1秒一個
shootCell.birthRate = 2.f;
// 粒子存在時間 1.02 上一個銷燬了下一個再發出來
shootCell.lifetime = 1.02f;
// 粒子速度和速度範圍 默認是發射模式方向的加速度⭐️
shootCell.velocity = 600.f;
shootCell.velocityRange = 100.f;
// Y方向的加速度 模擬重力影響 發射會感受收到向下的阻礙
shootCell.yAcceleration = 150.f;
// 發射角度範圍 看着更像是到處在放煙火🎆
shootCell.emissionRange = M_PI * 0.25;
shootCell.scale = 0.05;
shootCell.color = [[UIColor redColor] CGColor];
shootCell.greenRange = 1.f;
shootCell.redRange = 1.f;
shootCell.blueRange = 1.f;
shootCell.contents = (id)[[UIImage imageNamed:@"shoot_white"] CGImage];
// 煙火在發射的過程中自轉
shootCell.spinRange = M_PI; // 自轉360度
// 爆炸粒子效果
CAEmitterCell * explodeCell = [CAEmitterCell emitterCell];
explodeCell.name = @"explodeCell";
explodeCell.birthRate = 1.f;
explodeCell.lifetime = 0.5f;
explodeCell.velocity = 0.f;
explodeCell.scale = 2.5;
explodeCell.redSpeed = -1.5; //爆炸的時候變化顏色
explodeCell.blueRange = 1.5; //爆炸的時候變化顏色
explodeCell.greenRange = 1.f; //爆炸的時候變化顏色
// 火花粒子效果
CAEmitterCell * sparkCell = [CAEmitterCell emitterCell];
sparkCell.name = @"sparkCell";
sparkCell.birthRate = 400.f;
sparkCell.lifetime = 1.5f;
sparkCell.velocity = 125.f;
sparkCell.yAcceleration = 75.f; // 模擬重力影響
sparkCell.emissionRange = M_PI * 2; // 360度
sparkCell.scale = 1.2f;
sparkCell.contents = (id)[[UIImage imageNamed:@"star_white_stroke"] CGImage];
sparkCell.redSpeed = 0.4;
sparkCell.greenSpeed = -0.1;
sparkCell.blueSpeed = -0.1;
sparkCell.alphaSpeed = -0.25;
sparkCell.spin = M_PI * 2;
// 添加動畫 每個粒子效果 都可以添加後續動畫
fireworksLayer.emitterCells = @[shootCell];
// ⭐️粒子添加粒子,再添加粒子,就自動完成了煙火效果
shootCell.emitterCells = @[explodeCell];
explodeCell.emitterCells = @[sparkCell];
運行效果如下:
需要注意的屬性疊加
看到上面有【發射源形狀】【發射模式】兩個枚舉類型,在這裏要和大家說一聲,這兩個枚舉類型在使用的時候不好區分而且效果太模糊,給大家看一下運行圖,一共有四種發射模式和六種發射源形狀,大家可以看一下:
總結
想要做好各種粒子發射動畫,最關鍵的幾個點如下:
layer需要注意的:
// 發射源的形狀 是枚舉類型
emitterLayer.emitterShape = kCAEmitterLayerLine;
// 發射模式 枚舉類型
emitterLayer.emitterMode = kCAEmitterLayerSurface;
cell需要注意的:
// 設置經緯度(方向)(⭐️⭐️需要在 kCAEmitterLayerPoint 的情況下搭配使用)
showCell.emissionLongitude 上(-M_PI_2) 下(M_PI_2) 左(M_PI) 右(M_PI_4) 通常使用這個
showCell.emissionLatitude 前(-M_PI_2) 後(M_PI_2) 左(M_PI) 右(M_PI_4)
// 設置角度,控制發射範圍(受到經緯度的影響)
showCell.emissionRange // 圍繞X軸向左【指定度數覆蓋範圍】發射
鏈接: https://pan.baidu.com/s/1RpD7pOki6Y3eaBREyOfeBA 提取碼: 9ehx