【iOS】CALayer之CAEmitterLayer粒子發(fā)射器的神奇效果

想必以前QQ空間的點贊效果大家都知道吧,點贊之后按鈕周圍會有一圈爆裂的小圓點凿傅;還有微信的紅包雨表情動畫等缠犀,以及煙花,火焰效果聪舒。這些看似很炫酷的動畫可能讓我們敬而遠之辨液,但是其實iOS封裝的很好,利用簡單的幾行代碼就能完成很炫酷的動畫效果箱残。由于目前正在玩兒iOS動畫的內容滔迈,利用iOS的CAEmitterLayer結合CAEmitterCell能夠達這些效果止吁。不BB了,先上幾個效果圖燎悍。代碼已傳githubEmitterAnimation敬惦。

紅包雨
點贊效果

馬丹 有沒有辦法一次性放很多個gif呀。间涵。仁热。。勾哩。。举哟。


CAEmitterLayerCAEmitterCell

CAEmitterLayerCALayer的一個常用子類,CALayer的子類有很多思劳,如果能很好的使用它們會得到一些意想不到的效果。CAEmitterLayer就是其中之一妨猩,CAEmitterLayer是用于實現(xiàn)基于Core Animation的粒子發(fā)生器系統(tǒng)潜叛。

`CALayer`的常用子類

所謂粒子,就是很多小顆粒壶硅,當讓QQ空間的點贊動畫的粒子也可以不用CAEmitterLayer粒子發(fā)生器來實現(xiàn)威兜,不過這樣會麻煩很多。在粒子系統(tǒng)中庐椒,CAEmitterLayer是用來發(fā)射粒子的椒舵,他所發(fā)射的粒子就是CAEmitterCell(當然粒子也可以發(fā)射粒子,也就是CAEmitterCell也可以發(fā)射CAEmitterCell)约谈”仕蓿可以認為CAEmitterLayerCAEmitterCell的工廠,通過不同的設置就會不斷的產生想要的粒子棱诱。

原理其實很簡單泼橘,但是動畫就是這樣,需要花時間去理解屬性迈勋,只有很好的用它的屬性炬灭,才能達到很炫酷的效果。查看API會發(fā)現(xiàn)CAEmitterLayerCAEmitterCell的屬性都是很多的靡菇,并且有很多相同的屬性重归。在CAEmitterLayer中,一些屬性決定了粒子從什么樣的幾何特性上發(fā)射出來镰官,這個幾何特性包括了位置提前,形狀,大小泳唠,并且還有一些渲染屬性狈网,用于一些渲染的效果。另外一些屬性CAEmitterLayerCAEmitterCell都有的,在這里可能會迷糊拓哺,但是API說明的很清楚勇垛,CAEmitterLayer的這些屬性會作為CAEmitterCell相同屬性的系數(shù),舉個??士鸥,如果CAEmitterCellbirthRate = 10(每秒產生的粒子數(shù)量)闲孤,其所屬的CAEmitterLayerbirthRate = 2,那么在其他參數(shù)默認的情況下烤礁,這個CAEmitterCell總的每秒產生的粒子數(shù)量是10 * 2 = 20 讼积。也就是每秒會產生20個這樣的粒子。

另外脚仔,會發(fā)現(xiàn)CAEmitterCell的很多屬性都帶有一個Range勤众,比如scaleRangevelocityRange鲤脏,這些決定粒子自身的一些特性的屬性大多都是以“中間值” + 范圍(Range)的方式表示的们颜。再舉個??,比如scale = 0.5(縮放值)和scaleRange = 0.2(縮放的范圍)猎醇,那么表示的實際CAEmitterCell的縮放就是scale±scaleRange窥突,即0.3~0.7這個范圍。

紅包雨demo

初步了解了這些之后硫嘶,我們就可以跟著代碼來實現(xiàn)實現(xiàn)一個紅包雨的功能阻问。實現(xiàn)起來很簡單,只要設置好屬性就行了音半,這些屬性的詳細含義會在下面的篇幅仔細講解则拷,先來試下一個小demo。就是最開始的第個效果圖曹鸠。

實現(xiàn)步驟
  • 設置CAEmitterLayer以及它的一些模式煌茬,并添加到要顯示的view的圖層上,當然也可以替換view的圖層
  • 給這個CAEmitterLayer配置CAEmitterCell彻桃。
  • 沒有第三步了坛善。
  1. 設置CAEmitterLayer以及它的一些模式,并添加到要顯示的view的圖層上邻眷,當然也可以替換view的圖層眠屎。這里是直接添加到控制器的viewlayer上的,這個viewlayer是一個calyer類型的肆饶,如果想替換掉calyer改衩,可以自定義view,并在view里面重寫如下方法即可實現(xiàn)替換
// 替換view的layer
+ (Class)layerClass{return [CAEmitterLayer class];}

這里并沒有替換驯镊,而是直接添加葫督。當然為了后面方便這里把CAEmitterLayer設置為屬性竭鞍。詳細代碼如下,可以看注釋

@interface ViewController ()
@property (nonatomic, strong) CAEmitterLayer * redpacketLayer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self redpacketRain];
    
}

/**
 * 紅包雨
 */
- (void)redpacketRain{
    
    // 1. 設置CAEmitterLayer
    CAEmitterLayer * redpacketLayer = [CAEmitterLayer layer];
    [self.view.layer addSublayer:redpacketLayer];
    self.redpacketLayer = redpacketLayer;
    
    redpacketLayer.emitterShape = kCAEmitterLayerLine;  // 發(fā)射源的形狀 是枚舉類型
    redpacketLayer.emitterMode = kCAEmitterLayerSurface; // 發(fā)射模式 枚舉類型
    redpacketLayer.emitterSize = self.view.frame.size; // 發(fā)射源的size 決定了發(fā)射源的大小
    redpacketLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10); // 發(fā)射源的位置
    redpacketLayer.birthRate = 0.f; // 每秒產生的粒子數(shù)量的系數(shù)
}

到這里CAEmitterLayer的就設置完了橄镜,需要注意的是發(fā)射源的emitterPosition這個屬性偎快,是將它放在了頂部,實現(xiàn)從天上掉下來的效果洽胶。

  1. 給這個CAEmitterLayer配置CAEmitterCell晒夹。在redpacketRain方法里面添加如下代碼。值得注意的是姊氓,粒子的內容contents是一個CGImageRef類型的丐怯,用UIImage需要轉換為CGImage.
    // 2. 配置cell
    CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
    snowCell.contents = (id)[[UIImage imageNamed:@"red_paceket"] CGImage];  // 粒子的內容 是CGImageRef類型的
    
    snowCell.birthRate = 10.f;  // 每秒產生的粒子數(shù)量
    snowCell.lifetime = 20.f;  // 粒子的生命周期
    
    snowCell.velocity = 8.f;  // 粒子的速度
    snowCell.yAcceleration = 1000.f; // 粒子再y方向的加速的
    
    snowCell.scale = 0.5;  // 粒子的縮放比例
    
    redpacketLayer.emitterCells = @[snowCell];  // 粒子添加到CAEmitterLayer上

  1. 再添加一個按鈕,通過用KVC設置CAEmitterLayerbirthRate來實現(xiàn)動畫的開始和結束他膳。
- (IBAction)redpacketClick:(id)sender {
    
    [self.redpacketLayer setValue:@1.f forKeyPath:@"birthRate"];
    
    [self performSelector:@selector(endRedpacketAnimation) withObject:nil afterDelay:2.f];
}

- (void)endRedpacketAnimation{
    [self.redpacketLayer setValue:@0.f forKeyPath:@"birthRate"];
}
  1. run之后點擊按鈕就會出現(xiàn)上圖的效果了响逢。

CAEmitterLayerCAEmitterCell的屬性詳解

實現(xiàn)上面的小demo是不是很簡單?不到20行代碼而已棕孙,用到的屬性和也很少。那么下雨下雪的效果也是這樣實現(xiàn)的些膨,只不過是修改屬性值蟀俊。但是這些效果不夠炫酷,要實現(xiàn)炫酷的效果得先了解各個屬性的含義订雾,那么接下來花大量的篇幅講解CAEmitterLayerCAEmitterCell的屬性肢预。

CAEmitterLayer常用屬性

@property(nullable, copy) NSArray<CAEmitterCell *> *emitterCells; // 用來裝粒子的數(shù)組
@property float birthRate; // 粒子產生系數(shù),默認1.0
@property float lifetime; // 粒子的生命周期系數(shù), 默認1.0
@property CGPoint emitterPosition; // 決定了粒子發(fā)射形狀的中心點
@property CGFloat emitterZPosition;
@property CGSize emitterSize; // 發(fā)射源的尺寸大小
@property CGFloat emitterDepth;
@property(copy) NSString *emitterShape; // 發(fā)射源的形狀
@property(copy) NSString *emitterMode; // 發(fā)射模式
@property(copy) NSString *renderMode; // 渲染模式
@property BOOL preservesDepth;
@property float velocity; // 粒子速度系數(shù), 默認1.0
@property float scale; // 粒子的縮放比例系數(shù), 默認1.0
@property float spin; // 粒子的自旋轉速度系數(shù), 默認1.0
@property unsigned int seed; // 隨機數(shù)發(fā)生器

CAEmitterLayer里面的API里面的所有屬性都已經貼出來并作了說明洼哎,看看注釋并調試一下就能理解大部分烫映,接下來重點說說一些常用的屬性

1. CAEmitterLayer控制粒子發(fā)射位置和形狀的屬性

CAEmitterLayer發(fā)射的粒子并不是雜亂無章的,我們可以設置它發(fā)射粒子時的位置噩峦、幾何圖形等锭沟。通過以下屬性去配置:

  • emitterPosition:決定發(fā)射源的中心點,如果比如上面的demo中設置的為CGPointMake(self.view.bounds.size.width * 0.5, -10)识补,那么x軸方向上就是在view的中心點,然后再設置emitterSize = CGSizeMake(40, 0);的話族淮,那么就是self.view.bounds.size.width * 0.5的左右兩邊各20。API中還提供了一個emitterZPosition,這個是用在三維坐標中的凭涂,筆者暫時對三維的沒有研究祝辣。
  • emitterSize: 決定發(fā)射源的大小
  • emitterShape:表示粒子從什么形狀發(fā)射出來,它并不是表示粒子自己的形狀切油。是一個枚舉類型蝙斜,提供如下類型可供選擇:
kCAEmitterLayerPoint
kCAEmitterLayerLine
kCAEmitterLayerRectangle
kCAEmitterLayerCuboid
kCAEmitterLayerCircle
kCAEmitterLayerSphere
  1. kCAEmitterLayerPoint:點形狀,發(fā)射源的形狀就是一個點澎胡,位置在上面position設置的位置
  2. kCAEmitterLayerLine:線形狀孕荠,發(fā)射源的形狀是一條線娩鹉,位置在rect的橫向的位于垂直方向中間那條
  3. kCAEmitterLayerRectangle:矩形狀,發(fā)射源的形狀是一個矩形岛琼,就是上面生成的那個矩形rect
  4. kCAEmitterLayerCuboid:立體矩形形狀(3D)底循,發(fā)射源是一個立體矩形,這里要生效的話需要設置z方向的數(shù)據(jù)槐瑞,如果不設置就同矩形狀
  5. kCAEmitterLayerCircle:圓形形狀熙涤,發(fā)射源是一個圓形,形狀為矩形包裹的那個圓困檩,二維的
  6. kCAEmitterLayerSphere:立體圓形(3D)祠挫,三維的圓形,同樣需要設置z方向數(shù)據(jù)悼沿,不設置則通二維一樣

這些形狀可以在調試的時候修改來看看有什么不同等舔,比如我們設置的紅包效果,就是用的kCAEmitterLayerLine糟趾,結合了emitterSize來是實現(xiàn)從頂部掉下來的效果慌植,而emitterSizeheight其實是被忽略的。接下來我們看如下代碼的效果圖解:

redpacketLayer.emitterPosition = CGPointMake(100, 100);
redpacketLayer.emitterSize = CGSizeMake(20, 0);
redpacketLayer.emitterShape = kCAEmitterLayerLine;

達到的效果

emitterShape的幾種模式其實很好理解义郑,以emitterPosition的點為中心蝶柿,然后作一個對應的形狀,如直線非驮、圓形交汤、矩形,在這個形狀上產生相應的粒子劫笙。

  • emitterMode:發(fā)射模式芙扎,這個字段規(guī)定了在特定形狀上發(fā)射的具體形式是什么。它的作用其實就是進一步決定發(fā)射的區(qū)域是在發(fā)射形狀的哪一部份填大。
kCAEmitterLayerPoints
kCAEmitterLayerOutline
kCAEmitterLayerSurface
kCAEmitterLayerVolume
  1. kCAEmitterLayerPoints:點模式戒洼,發(fā)射器是以點的形式發(fā)射粒子。發(fā)射點就是形狀的某個特殊的點栋盹,比如shap是一個點的話施逾,那么這個點就是中心點,如果是圓形例获,那么就是圓心汉额。
  2. kCAEmitterLayerOutline:輪廓模式,從形狀的邊界上發(fā)射粒子榨汤。
  3. kCAEmitterLayerSurface:表面模式蠕搜,從形狀的表面上發(fā)射粒子。
  4. kCAEmitterLayerVolume:是相對于3D形狀的“球體內”或“立方體內”發(fā)射收壕,筆者暫時也不是很了解3D的妓灌。
2. CAEmitterLayer決定粒子系數(shù)的屬性
  • birthRate: 粒子產生系數(shù)轨蛤,默認1.0;每個粒子cell的產生率乘以這個粒子產生系數(shù)虫埂,得出每一秒產生這個粒子的個數(shù)祥山。 即:每秒粒子產生個數(shù) = layer.birthRate * cell.birthRate ;
  • lifetime:粒子的生命周期系數(shù)掉伏,默認1.0缝呕。計算方式同上;
  • velocity:粒子速度系數(shù), 默認1.0斧散。計算方式同上供常;
  • scale:粒子的縮放比例系數(shù), 默認1.0。計算方式同上鸡捐;
  • spin:自旋轉速度系數(shù), 默認1.0栈暇。計算方式同上;
3.CAEmitterLayer決定粒子內容的屬性
  • emitterCells:用來裝粒子的數(shù)組箍镜。每種粒子就是一個CAEmitterCell源祈。在API中可以看到CAEmitterCell是服從CAMediatiming協(xié)議的,可以通過beginTime來控制subCell的出現(xiàn)時機色迂。

CAEmitterCell常用屬性

@property(nullable, copy) NSString *name; // 粒子名字新博, 默認為nil
@property(getter=isEnabled) BOOL enabled; 
@property float birthRate; // 粒子的產生率,默認0
@property float lifetime; // 粒子的生命周期,以秒為單位脚草。默認0
@property float lifetimeRange; // 粒子的生命周期的范圍,以秒為單位原献。默認0
@property CGFloat emissionLatitude;// 指定緯度,緯度角代表了在x-z軸平面坐標系中與x軸之間的夾角馏慨,默認0: 
@property CGFloat emissionLongitude; // 指定經度,經度角代表了在x-y軸平面坐標系中與x軸之間的夾角,默認0:
@property CGFloat emissionRange; //發(fā)射角度范圍,默認0姑隅,以錐形分布開的發(fā)射角度写隶。角度用弧度制。粒子均勻分布在這個錐形范圍內;
@property CGFloat velocity; // 速度和速度范圍讲仰,兩者默認0
@property CGFloat velocityRange;
@property CGFloat xAcceleration; // x,y,z方向上的加速度分量,三者默認都是0
@property CGFloat yAcceleration;
@property CGFloat zAcceleration;
@property CGFloat scale; // 縮放比例, 默認是1
@property CGFloat scaleRange; // 縮放比例范圍,默認是0
@property CGFloat scaleSpeed; // 在生命周期內的縮放速度,默認是0
@property CGFloat spin; // 粒子的平均旋轉速度慕趴,默認是0
@property CGFloat spinRange; // 自旋轉角度范圍,弧度制,默認是0
@property(nullable) CGColorRef color; // 粒子的顏色,默認白色
@property float redRange; // 粒子顏色red,green,blue,alpha能改變的范圍,默認0
@property float greenRange;
@property float blueRange;
@property float alphaRange;
@property float redSpeed; // 粒子顏色red,green,blue,alpha在生命周期內的改變速度,默認都是0
@property float greenSpeed;
@property float blueSpeed;
@property float alphaSpeed;
@property(nullable, strong) id contents; // 粒子的內容鄙陡,為CGImageRef的對象
@property CGRect contentsRect;
@property CGFloat contentsScale;
@property(copy) NSString *minificationFilter;
@property(copy) NSString *magnificationFilter;
@property float minificationFilterBias;
@property(nullable, copy) NSArray<CAEmitterCell *> *emitterCells; // 粒子里面的粒子
@property(nullable, copy) NSDictionary *style;

CAEmitterCell里面的API里面的大部分屬性作了說明冕房,看看注釋并調試一下就能理解大部分,接下來重點說說一些常用的屬性趁矾。CAEmitterLayer就是粒子的工廠耙册,但是要實現(xiàn)效果就需要CAEmitterCell的幫助。

1.CAEmitterCell決定生命狀態(tài)的屬性
  • lifetime毫捣、lifetimeRange:粒子在系統(tǒng)上的生命周期详拙,即存活時間帝际,單位是秒。配合lifetimeRage來讓粒子生命周期均勻變化饶辙,以便可以讓粒子的出現(xiàn)和消失顯得更加離散蹲诀。
  • birthRate:每秒鐘產生的粒子的數(shù)量,是浮點數(shù)弃揽。對于這個數(shù)量為浮點數(shù)脯爪,在測試的時候可以靈活使用它。比如你想看粒子的運動狀態(tài)蹋宦,但是太多了可能會很迷糊披粟,這時候你把birthRate = 0.1f,其他參數(shù)不變冷冗,就能看到單個粒子的運動狀態(tài)守屉。
2.CAEmitterCell決定內容的屬性
  • contents:為CGImageRef的對象。關于contents會聯(lián)想到CALayer了蒿辙,在CALayer中展示靜態(tài)的圖片是需要用到這個屬性拇泛。提供一張圖片,作為粒子系統(tǒng)的粒子思灌。但是因為粒子系統(tǒng)可以給粒子上色俺叭,為了做出好的顏色變換效果,通常提供的圖片為純色的圖片泰偿,一般為白色熄守。
  • name:粒子的名字。初看沒什么用耗跛,但是當CAEmitterLayer里面有很多個cell的時候裕照,給每個cell設置好名字,要修改一些屬性以達到動畫效果的改變等调塌,就可以通過KVC拿到這個cell的某個屬性晋南。在后面的幾個demo中都用用到。
3.CAEmitterCell決定顏色狀態(tài)的屬性

粒子系統(tǒng)之所以能做出炫酷的效果羔砾,和它的色彩多樣化有必不可上的關系负间,在CAEmitterCell中提供了較多的顏色控制屬性這部分屬性讓你獲得了控制粒子顏色,顏色變化范圍和速度的能力姜凄,你可以憑借它來完成一些漸變的效果或其它構建在它之上的酷炫效果政溃。接下來就看看這些顏色屬性。

  • colorcolor是粒子的顏色屬性檀葛,這個顏色屬性的作用是給粒子上色玩祟,它的實現(xiàn)方法很簡單,就是將contents自身的顏色的RGBA值 * color的RGBA值屿聋,就得到最終的粒子的顏色空扎。為了很好的計算藏鹊,通常用白色的圖片作為contents,因為它的RGB都是255转锈,轉換為UIColor中的component就是1盘寡,用color乘上它就能得到color設置的顏色效果。
  • redRange撮慨、greenRange竿痰、blueRangealphaRange:這些是對應的color的RGBA的取值范圍,取值范圍為0~1砌溺,比如如下設置中
    snowCell.color = [[UIColor colorWithRed:0.1 green:0.2 blue:0.3 alpha:0.5]CGColor];
    snowCell.redRange = 0.1;
    snowCell.greenRange = 0.1;
    snowCell.blueRange = 0.1;
    snowCell.alphaRange = 0.1;

對應的RGBA的取值范圍就是:R(00.2)锡搜、G(0.10.3)讲竿、B(0.20.4)、A(0.40.6)。

  • redSpeed槽华、greenSpeed阅茶、blueSpeed吹榴、alphaSpeed:這些是對應的是粒子的RGBA的變化速度暖哨,取值范圍為0~1。表示每秒鐘的RGBA的變化率培慌。這個變化率的計算方式其實很簡單豁陆,先看下面的幾行代碼:
    snowCell.lifetime = 20.f;  // 粒子的生命周期
    snowCell.color = [[UIColor colorWithRed:0.f green:1.f blue:1.f alpha:1.f]CGColor];
    snowCell.redSpeed = 0.2;

這里設置了粒子顏色的RGBA,以及redSpeed吵护,其他的沒設置默認為0盒音。粒子的生命周期(lifetime)為20秒,那么這個粒子從產生到消失的時間就是20秒馅而。它的Red值為0里逆,redSpeed為0.2,那么在粒子的這個生命周期內用爪,粒子的每秒鐘的Rde值就會增加0.2 * 255,表現(xiàn)在外觀上的狀態(tài)就是粒子顏色在不斷變化,接近白色胁镐。最后粒子生命周期結束的時候偎血,粒子的color正好是RGBA(1,1,1,1)。當然個變化的速度也可以負數(shù)盯漂,計算方式相同颇玷。比如要設置煙花的效果,那么要讓在爆炸的過程中顏色變化就缆,就是通過這樣的設置達到的效果帖渠。

4.CAEmitterCell決定飛行軌跡的屬性。

CAEmitterLayer雖然控制了粒子的發(fā)射位置和形狀等竭宰,但是粒子的飛行同時也需要自身去決定空郊,比如粒子發(fā)射的角度份招、發(fā)散的范圍,自轉屬性等狞甚。那么接下來就說說這些屬性锁摔。

  • emissionLongitude: 指定經度,經度角代表了在x-y軸平面坐標系中與x軸之間的夾角,默認0哼审,弧度制谐腰。順時針方向為正。這樣解釋看起來不好懂涩盾,畫個圖就明白了十气。
    emissionLatitude

    粒子沿著X軸向右飛行,如果emissionLongtitude = 0那么粒子會沿著X軸向右飛行春霍,如果想沿著Y軸向下飛行砸西,那么可以設置emissionLongtitude = M_PI_2
  • emissionLatitude:這個和emissionLongitude的原理是一樣的终畅,只不過是在三維平面上的x-z軸上與x軸的夾角籍胯。
  • emissionRange:發(fā)射角度范圍,默認0,以錐形分布開的發(fā)射角度离福。角度用弧度制杖狼。粒子均勻分布在這個錐形范圍內。在二維平面中妖爷,若想要以錐形的形式發(fā)射粒子蝶涩,然粒子的發(fā)散范圍不是一條線,而是一個錐形區(qū)域(也可以叫做扇形)絮识,那么可以通過emissionRange來設置一個范圍绿聘。比如想沿Y軸向下成90度的錐形區(qū)域發(fā)散,那么可以通過如下代碼設置:
    snowCell.emissionLongitude = M_PI_2;
    snowCell.emissionRange = M_PI_4;

實現(xiàn)的效果如下:


實現(xiàn)效果

可以看到粒子是沿著Y軸向下成90度的一個發(fā)散角度次舌。如果想實現(xiàn)火焰等效果熄攘。就可以這樣,把角度調小一點即可彼念。

  • velocity挪圾、velocityRangexAcceleration 逐沙、yAcceleration哲思、zAcceleration:前面兩個是粒子的初速度和初速度的范圍,后面是三個分別是在x吩案、y棚赔、z軸方向的加速度,這個很好理解,初中就應該知道加速度的概念靠益,也就是每秒鐘速度的變化量丧肴。在放煙花的效果中,煙花飛上天的過程中捆毫,模擬一個收重力影響的效果闪湾,就可以通過yAcceleration模擬一個重力加速度的效果。
  • spin绩卤,spinRange:這兩個屬性很重要途样,是粒子的自轉屬性。在粒子被發(fā)射出去之后濒憋,想要實現(xiàn)自轉何暇,就需要用到他們。粒子的自轉是以弧度制來計算的凛驮,表示每秒鐘粒子自轉的弧度數(shù)裆站。spin為正數(shù)代表粒子是順時針旋轉的,為負數(shù)的話就是逆時針選轉了黔夭。舉個??:粒子的生命周期就是20秒宏胯,那么你想讓你的粒子這個生命周期內剛好自轉12周,若spinRange為0本姥,那么粒子的spin值就應該為((PI/180)*360 * 2)/20肩袍,就得到了每秒需要轉動的弧度數(shù)。
5.CAEmitterCell子粒子的屬性
  • emitterCells:看到CAEmitterCell的這個屬性的時候或許會有些疑惑婚惫,不用驚訝氛赐,前面說過CAEmitterLayer可以產生cell,通用cell也可以產生cell先舷。那么這個屬性就和CAEmitterLayer中的emitterCells一樣艰管,也是一個數(shù)組。這里有幾個需要注意的地方:
    1. 若給cell設置了subCell蒋川,若想控制subCell的方向牲芋,那么得考慮父cell的方向屬性,也就是emissionLongtitudeemissionLatitude這兩個屬性的情況捺球。
    2. 不管父粒子cell是從什么樣的形狀上發(fā)射出來的街图,若要發(fā)射subCell,subCell總是從kCAEmitterLayerPoint形狀上由父粒子的中心發(fā)射出來的懒构。

造幾個小Demo

理解了CAEmitterLayerCAEmitterCell的屬性之后,通過粒子系統(tǒng)實現(xiàn)一些炫酷的動畫效果就很簡單了耘擂。接下來對實現(xiàn)的幾個小demo效果作個思路分享胆剧,歡迎提供更好的方法~。

QQ空間點贊動畫

動畫分析
  • 點贊的時候先是把按鈕放大再縮小,這個可以用核心動畫里面的關鍵幀動畫CAKeyframeAnimation實現(xiàn)
  • 放大后馬上回有一圈的粒子發(fā)射秩霍,這就是粒子系統(tǒng)實現(xiàn)
  • 然后從贊到取消贊沒有動畫效果
實現(xiàn)思路
  • 自定義按鈕篙悯,重寫setHighlighted方法去掉高亮狀態(tài)。提供兩張圖片铃绒,用于默認狀態(tài)和選中狀態(tài)鸽照。
  • 配置發(fā)射源CAEmitterLayer和粒子CAEmitterCell。由于CAEmitterLayerbirthRate默認為1颠悬,CAEmitterCellbirthRate默認為0矮燎,那么先不設置這兩個屬性。給cell設置好name赔癌,然后自定義一個動畫開始的方法诞外,在這里面通過KVC設置CAEmitterCellbirthRate以實現(xiàn)動畫
/**
 * 開始動畫
 */
- (void)startAnimation{
    
    // 用KVC設置顆粒個數(shù)
    [self.explosionLayer setValue:@1000 forKeyPath:@"emitterCells.explosionCell.birthRate"];
    
    // 開始動畫
    self.explosionLayer.beginTime = CACurrentMediaTime();
    // 延遲停止動畫
    [self performSelector:@selector(stopAnimation) withObject:nil afterDelay:0.15];
}

/**
 * 動畫結束
 */
- (void)stopAnimation{
    // 用KVC設置顆粒個數(shù)
    [self.explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosionCell.birthRate"];
    [self.explosionLayer removeAllAnimations];
}
  • 重寫按鈕的setSelected方法,在里面通過關鍵幀動畫實現(xiàn)縮放灾票。
/**
 * 選中狀態(tài) 實現(xiàn)縮放
 */
- (void)setSelected:(BOOL)selected{
    [super setSelected:selected];
    
    // 通過關鍵幀動畫實現(xiàn)縮放
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"transform.scale";
    if (selected) {  // 從沒有點擊到點擊狀態(tài) 會有爆炸的動畫效果
        animation.values = @[@1.5,@2.0, @0.8, @1.0];
        animation.duration = 0.5;
        
        animation.calculationMode = kCAAnimationCubic;
        [self.layer addAnimation:animation forKey:nil];

        // 讓放大動畫先執(zhí)行完畢 再執(zhí)行爆炸動畫
        [self performSelector:@selector(startAnimation) withObject:nil afterDelay:0.25];
    }else{ // 從點擊狀態(tài)normal狀態(tài) 無動畫效果 如果點贊之后馬上取消 那么也立馬停止動畫
        [self stopAnimation];
    }
}

結語

還有幾個動畫的思路就不啰嗦了峡谊,實現(xiàn)起來都很簡單,關鍵是要去理解這些屬性的作用刊苍。另外動畫做起來即使費時間既们,要自己去理解屬性的作用的話需要花時間調試對比,其實用其他方式也可以實現(xiàn)這樣的效果正什,但是CAEmitterLayer 基于GPU,做這些效果的時候比較方便啥纸。demo已經上傳github了,提供了下雨埠忘、下雪脾拆、紅包雨、五彩小球莹妒、愛心名船、火焰、煙花等效果旨怠,值得一說的是渠驼,煙花需要三個cell,一個提供發(fā)射的shootCell鉴腻,一個用于爆炸的explodeCell,還有一個用于火花的sparkCell,這些都是父子關系迷扇,一個cell生命周期完了另外一個再出來。這些可以查看代碼體會爽哎,都有注釋~蜓席。EmitterAnimation

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市课锌,隨后出現(xiàn)的幾起案子厨内,更是在濱河造成了極大的恐慌祈秕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雏胃,死亡現(xiàn)場離奇詭異请毛,居然都是意外死亡,警方通過查閱死者的電腦和手機瞭亮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門方仿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人统翩,你說我怎么就攤上這事仙蚜。” “怎么了唆缴?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵鳍征,是天一觀的道長。 經常有香客問我面徽,道長艳丛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任趟紊,我火速辦了婚禮氮双,結果婚禮上,老公的妹妹穿的比我還像新娘霎匈。我一直安慰自己戴差,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布铛嘱。 她就那樣靜靜地躺著暖释,像睡著了一般。 火紅的嫁衣襯著肌膚如雪墨吓。 梳的紋絲不亂的頭發(fā)上球匕,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音帖烘,去河邊找鬼亮曹。 笑死,一個胖子當著我的面吹牛秘症,可吹牛的內容都是我干的照卦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼乡摹,長吁一口氣:“原來是場噩夢啊……” “哼役耕!你這毒婦竟也來了?” 一聲冷哼從身側響起聪廉,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤瞬痘,失蹤者是張志新(化名)和其女友劉穎氏义,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體图云,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年邻邮,在試婚紗的時候發(fā)現(xiàn)自己被綠了竣况。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡筒严,死狀恐怖丹泉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情鸭蛙,我是刑警寧澤摹恨,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站娶视,受9級特大地震影響晒哄,放射性物質發(fā)生泄漏。R本人自食惡果不足惜肪获,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一寝凌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孝赫,春花似錦较木、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至致开,卻和暖如春峰锁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背喇喉。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工祖今, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拣技。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓千诬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膏斤。 傳聞我的和親對象是個殘疾皇子徐绑,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345