之前說到貝塞爾曲線,今天說CALayer恶座,哈哈哈,承上啟下沥阳,放一個表情與上一篇相呼應(yīng)跨琳。
CALayer
首先,CALayer其實(shí)自身有很多情況下自帶隱式動畫桐罕,但是需要注意的是UIView的根Layer是沒有隱式動畫的脉让。下面看一下CALayer的幾個重要的屬性:
對于大多數(shù)開發(fā)者老說,CALayer是很熟悉的一個名詞功炮,但是對于它的屬性可能一知半解溅潜,上表大致說明了CALayer的幾個重要屬性的作用以及是否支持隱式動畫,下面著重介紹幾個點(diǎn):
(1)frame屬性
frame不支持隱式動畫薪伏,所以通常使用bounds和position來設(shè)置layer的位置和大小
(2)contents
設(shè)置layer的contents可以為layer添加顯示內(nèi)容滚澜,最直接的便是將UIImage轉(zhuǎn)化為CGImageRef賦值,其與backgroundColor的關(guān)系就相當(dāng)于UIImageView的image和backgorundColor的關(guān)系嫁怀。
(3)錨點(diǎn) anchorPoint
錨點(diǎn)的取值范圍為(0~1设捐,0~1),標(biāo)示此點(diǎn)相對于寬高的比例塘淑,默認(rèn)點(diǎn)(0.5萝招,0.5),錨點(diǎn)的位置對圖層的位置以及某些動畫的重心起到?jīng)Q定性的作用存捺,通過錨點(diǎn)計算圖層位置-->中心點(diǎn)相對于父父層的位置永遠(yuǎn)不變槐沼,錨點(diǎn)于中心點(diǎn)重合。以旋轉(zhuǎn)動畫為例召噩,錨點(diǎn)是旋轉(zhuǎn)的中心母赵。
(4)mask
mask的作用就相當(dāng)于PS中的蒙版,在一些圖層處理上具有很大的優(yōu)勢(注:蒙版透明色為過濾掉指定layer的區(qū)域內(nèi)容具滴,不透明色為顯示制定圖層的區(qū)域內(nèi)容)
CALayer的子類
CALayer的子類有很多凹嘲,下面說幾個比較常用的:
CAShapeLayer
看一下CAShapeLayer相對于CALayer多出來的屬性:
path
CAShapeLayer的path屬性是他如此牛逼的一個重要起點(diǎn),也是它和貝塞爾曲線緊密連接一個入口构韵,他決定了我們要在圖層上畫一個什么形狀周蹭。(注:當(dāng)與貝塞爾曲線一起使用的時候趋艘,生成的曲線的位置是相對于生成的layer的,所以當(dāng)你利用貝塞爾曲線設(shè)置了path后凶朗,再設(shè)置layer的position和bounds你會感覺很奇怪瓷胧,最簡單的方式就是單純利用貝塞爾曲線決定圖層的位置和大小)
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
//shapeLayer.position = CGPointMake(100, 100);
//shapeLayer.bounds = CGRectMake(0, 0, 100, 100);
//shapeLayer.anchorPoint = CGPointMake(0, 0);
shapeLayer.path = bezierPath.CGPath;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [UIColor blueColor].CGColor;
shapeLayer.lineWidth = 10;
self.view.layer.mask = shapeLayer;
//[self.view.layer addSublayer:shapeLayer];
fillColor 和 fillRule
fillColor
即layer的path的填充顏色棚愤,fillRule
屬性用于指定使用哪一種算法去判斷畫布上的某區(qū)域是否屬于該圖形“內(nèi)部” (內(nèi)部區(qū)域?qū)⒈惶畛洌┐晗簟σ粋€簡單的無交叉的路徑,哪塊區(qū)域是“內(nèi)部” 是很直觀清除的宛畦。但是瘸洛,對一個復(fù)雜的路徑,比如自相交或者一個子路徑包圍另一個子路徑次和,“內(nèi)部”的理解就不那么明了反肋。
fillRule提供兩種選項(xiàng)用于指定如何判斷圖形的內(nèi)部”
kCAFillRuleNonZero
,kCAFillRuleEvenOdd
:
-(void)checkFillRule{
UIBezierPath *path = [[UIBezierPath alloc] init];
CGPoint circleCenter = self.view.center;
[path moveToPoint:CGPointMake(circleCenter.x + 50, circleCenter.y)];
[path addArcWithCenter:circleCenter radius:50 startAngle:0 endAngle:2*M_PI clockwise:YES];
[path moveToPoint:CGPointMake(circleCenter.x + 100, circleCenter.y)];
[path addArcWithCenter:circleCenter radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
[path moveToPoint:CGPointMake(circleCenter.x + 150, circleCenter.y)];
[path addArcWithCenter:circleCenter radius:150 startAngle:0 endAngle:2*M_PI clockwise:YES];
//create shape layer
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor redColor].CGColor;
shapeLayer.fillColor = [UIColor greenColor].CGColor;
shapeLayer.fillRule = kCAFillRuleNonZero;
//shapeLayer.fillRule = kCAFillRuleEvenOdd;
shapeLayer.lineWidth = 5;
shapeLayer.lineJoin = kCALineJoinBevel;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.path = path.CGPath;
//add it to our view
[self.view.layer addSublayer:shapeLayer];
}
當(dāng)fillRule為kCAFillRuleNonZero
時:
當(dāng)fillRule為
kCAFillRuleEvenOdd
時:通過上面的代碼再加上下面抄襲的描述,應(yīng)該能夠相當(dāng)清晰的理解這其中的意義踏施。
kCAFillRuleNonZero
字面意思是“非零”石蔗。按該規(guī)則,要判斷一個點(diǎn)是否在圖形內(nèi)畅形,從該點(diǎn)作任意方向的一條射線养距,然后檢測射線與圖形路徑的交點(diǎn)情況。從0開始計數(shù)束亏,路徑從左向右穿過射線則計數(shù)加1铃在,從右向左穿過射線則計數(shù)減1。得出計數(shù)結(jié)果后碍遍,如果結(jié)果是0,則認(rèn)為點(diǎn)在圖形外部阳液,否則認(rèn)為在內(nèi)部怕敬。下圖演示了kCAFillRuleNonZero規(guī)則 :
kCAFillRuleEvenOdd
字面意思是“奇偶”。按該規(guī)則帘皿,要判斷一個點(diǎn)是否在圖形內(nèi)东跪,從該點(diǎn)作任意方向的一條射線,然后檢測射線與圖形路徑的交點(diǎn)的數(shù)量鹰溜。如果結(jié)果是奇數(shù)則認(rèn)為點(diǎn)在內(nèi)部虽填,是偶數(shù)則認(rèn)為點(diǎn)在外部。下圖演示了kCAFillRuleEvenOdd 規(guī)則:
strokeColor
線顏色
strokeStart strokeEnd
兩者的取值都是0~1曹动,決定貝塞爾曲線的劃線百分比斋日,對應(yīng)值的改變支持隱式動畫。
UIBezierPath* bezierPath_rect = [UIBezierPath bezierPathWithRect:CGRectMake(30, 50, 100, 100)];
bezierPath_rect.lineWidth = 10;
CAShapeLayer* shapeLayer = [CAShapeLayer layer];
shapeLayer.path = bezierPath_rect.CGPath;
shapeLayer.fillColor = [UIColor redColor].CGColor;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.lineWidth = 10;
shapeLayer.strokeStart = 0;
shapeLayer.strokeEnd = 0.3;
[self.view.layer addSublayer:shapeLayer];
運(yùn)行結(jié)果:
lineWidth
線寬
miterLimit
最大斜接長度墓陈,只有l(wèi)ineJoin屬性為kCALineJoinMiter時miterLimit才有效恶守,當(dāng)銜接角度太小時第献,斜接長度就會很大,如果設(shè)置了 miterLimit
并且當(dāng)斜接長度大于這個值時兔港,便會對應(yīng)裁切掉多余區(qū)域:
設(shè)置
miterLimit
后:lineCap
線端點(diǎn)類型庸毫,也就是對應(yīng)曲線結(jié)束的點(diǎn)的顯示樣式。
lineJoin
連接點(diǎn)類型衫樊,也就是對應(yīng)曲線節(jié)點(diǎn)的位置的顯示樣式飒赃。
lineDashPattern
虛線設(shè)置,為一個數(shù)組科侈,數(shù)組中奇數(shù)位實(shí)線長度载佳,偶數(shù)位帶遍空白長度(注意:這里的奇數(shù),偶數(shù)以數(shù)組的第一個元素索引為1計算)
lineDashPhase
虛線開始的位置兑徘,可以使用此屬性做一個滾動的虛線框刚盈。
CAShapeLayer* dashLineShapeLayer = [CAShapeLayer layer];
//創(chuàng)建貝塞爾曲線
UIBezierPath* dashLinePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 200, 100) cornerRadius:20];
dashLineShapeLayer.path = dashLinePath.CGPath;
dashLineShapeLayer.position = CGPointMake(100, 100);
dashLineShapeLayer.fillColor = [UIColor clearColor].CGColor;
dashLineShapeLayer.strokeColor = [UIColor whiteColor].CGColor;
dashLineShapeLayer.lineWidth = 3;
dashLineShapeLayer.lineDashPattern = @[@(6),@(6)];
dashLineShapeLayer.strokeStart = 0;
dashLineShapeLayer.strokeEnd = 1;
dashLineShapeLayer.zPosition = 999;
//
[self.view.layer addSublayer:dashLineShapeLayer];
//
NSTimeInterval delayTime = 0.3f;
//定時器間隔時間
NSTimeInterval timeInterval = 0.1f;
//創(chuàng)建子線程隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//使用之前創(chuàng)建的隊(duì)列來創(chuàng)建計時器
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//設(shè)置延時執(zhí)行時間,delayTime為要延時的秒數(shù)
dispatch_time_t startDelayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC));
//設(shè)置計時器
dispatch_source_set_timer(_timer, startDelayTime, timeInterval * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(_timer, ^{
//執(zhí)行事件
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CGFloat _add = 3;
dashLineShapeLayer.lineDashPhase -= _add;
});
});
// 啟動計時器
dispatch_resume(_timer);
效果如圖:(視頻好像有點(diǎn)快...)
其實(shí)CAShapeLayer的用處很多挂脑,能實(shí)現(xiàn)很多動畫效果的同時藕漱,也可以實(shí)現(xiàn)很多蒙版效果,心有多大崭闲,功能就有多大肋联。
之前寫過一個點(diǎn)擊擴(kuò)散的庫,主要用到蒙版mask以及shapeLayer和核心動畫刁俭,您上眼:
//
// UIView+YSTransform.h
// JR_New_AnimationDemo
//
// Created by ys on 2016/3/20.
// Copyright ? 2016年 ys. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (YSTransform)<CAAnimationDelegate>
-(void)YSTransform_circleColor_toColor:(UIColor*)toColor Duration:(CGFloat)duration StartPoint:(CGPoint)startPoint;
-(void)YSTransform_circleImage_toImage:(UIImage*)toImage Duration:(CGFloat)duration StartPoint:(CGPoint)startPoint;
-(void)YSTransForm_beginZoom_max:(CGFloat)max min:(CGFloat)min;
-(void)YSTransForm_StopZoom;
@end
//
// UIView+YSTransform.m
// JR_New_AnimationDemo
//
// Created by ys on 2016/3/20.
// Copyright ? 2016年 ys. All rights reserved.
//
#import "UIView+YSTransform.h"
#import <objc/runtime.h>
@implementation UIView (YSTransform)
-(void)YSTransform_circleColor_toColor:(UIColor*)toColor Duration:(CGFloat)duration StartPoint:(CGPoint)startPoint{
CALayer *tempLayer = objc_getAssociatedObject(self, @"tempLayer");
if (!tempLayer) {
tempLayer = [[CALayer alloc] init];
tempLayer.bounds = self.bounds;
tempLayer.position = self.center;
tempLayer.backgroundColor = self.backgroundColor.CGColor;
[self.layer addSublayer:tempLayer];
objc_setAssociatedObject(self, @"tempLayer", tempLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//
tempLayer.contents = nil;
tempLayer.backgroundColor = toColor.CGColor;
CGFloat screenHeight = self.frame.size.height;
CGFloat screenWidth = self.frame.size.width;
CGRect rect = CGRectMake(startPoint.x, startPoint.y, 2, 2);
UIBezierPath *startPath = [UIBezierPath bezierPathWithOvalInRect:rect];
UIBezierPath *endPath = [UIBezierPath bezierPathWithArcCenter:startPoint radius:sqrt(screenHeight * screenHeight + screenWidth * screenWidth) startAngle:0 endAngle:M_PI*2 clockwise:YES];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = endPath.CGPath;
tempLayer.mask = maskLayer;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.delegate = self;
animation.fromValue = (__bridge id)(startPath.CGPath);
animation.toValue = (__bridge id)((endPath.CGPath));
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animation setValue:@"YSCircleColor_value" forKey:@"YSCircleColor_key"];
[maskLayer addAnimation:animation forKey:@"YSCircleColor"];
}
-(void)YSTransform_circleImage_toImage:(UIImage*)toImage Duration:(CGFloat)duration StartPoint:(CGPoint)startPoint{
CALayer *tempLayer = objc_getAssociatedObject(self, @"tempLayer");
if (!tempLayer) {
tempLayer = [[CALayer alloc] init];
tempLayer.bounds = self.bounds;
tempLayer.position = self.center;
tempLayer.backgroundColor = self.backgroundColor.CGColor;
[self.layer addSublayer:tempLayer];
objc_setAssociatedObject(self, @"tempLayer", tempLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
tempLayer.contents = (id)toImage.CGImage;
//
CGFloat screenHeight = self.frame.size.height;
CGFloat screenWidth = self.frame.size.width;
CGRect rect = CGRectMake(startPoint.x, startPoint.y, 2, 2);
UIBezierPath *startPath = [UIBezierPath bezierPathWithOvalInRect:rect];
UIBezierPath *endPath = [UIBezierPath bezierPathWithArcCenter:startPoint radius:sqrt(screenHeight * screenHeight + screenWidth * screenWidth) startAngle:0 endAngle:M_PI*2 clockwise:YES];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = endPath.CGPath;
tempLayer.mask = maskLayer;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.delegate = self;
animation.fromValue = (__bridge id)(startPath.CGPath);
animation.toValue = (__bridge id)((endPath.CGPath));
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animation setValue:@"YSCircleImage_value" forKey:@"YSCircleImage_key"];
[maskLayer addAnimation:animation forKey:@"YSCircleImage"];
}
//
-(void)YSTransForm_beginZoom_max:(CGFloat)max min:(CGFloat)min{
[UIView animateWithDuration:0.3 animations:^{
self.transform = CGAffineTransformMakeScale(max, max);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.transform = CGAffineTransformMakeScale(min, min);
} completion:^(BOOL finished) {
NSNumber *nextStop = objc_getAssociatedObject(self, @"nextAniStop");
if ([nextStop boolValue]) {
[UIView animateWithDuration:0.3 animations:^{
self.transform = CGAffineTransformMakeScale(1, 1);
} completion:^(BOOL finished) {
self.transform = CGAffineTransformMakeScale(1, 1);
objc_setAssociatedObject(self, @"nextAniStop", @(0), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}];
}else{
[self YSTransForm_beginZoom_max:max min:min];
}
}];
}];
}
-(void)YSTransForm_StopZoom{
objc_setAssociatedObject(self, @"nextAniStop", @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (flag) {
CALayer *tempLayer = objc_getAssociatedObject(self, @"tempLayer");
if ([anim valueForKey:@"YSCircleColor_key"]) {
self.layer.contents = nil;
self.backgroundColor = [UIColor colorWithCGColor:tempLayer.backgroundColor];
}else if ([anim valueForKey:@"YSCircleImage_key"]){
self.layer.contents = tempLayer.contents;
}
}
}
@end
效果如下:
另外橄仍,其實(shí)我們看到的很多酷炫的變幻莫測的動畫很多都是CAShapeLayer
或者Quartz 2D
繪圖配合幀率刷新的結(jié)果。來牍戚,有時間我給你講講啊侮繁。
CAGradientLayer
下面再說一個比較常用的子類CAGradientLayer
,我們一般使用它生成平滑的顏色過渡如孝。大致的效果如下:
同樣宪哩,我們還是從它的特有屬性入手:
colors
在Layer中現(xiàn)實(shí)的幾種顏色并完成完美過渡,和CAShapeLayer
的path
一樣第晰,colors
是CAGradientLayer
特殊屬性的起點(diǎn)锁孟,也就是x 顯示的要素。
locations
顏色區(qū)間分布比例茁瘦,默認(rèn)為線性均勻分布品抽。取值范圍為0~1遞增,一般來說其中的元素個數(shù)應(yīng)與colors中的元素個數(shù)相同甜熔,不同時系統(tǒng)會自行處理分布規(guī)則圆恤。
設(shè)置 gradientLayer.locations = @[@(0.3),@(0.7)];
startPoint endPoint
startPoint
決定了變色范圍的起始點(diǎn),endPoint
決定了變色范圍的結(jié)束點(diǎn)纺非,兩者的連線決定變色的趨勢:
注意:
locations
是相對于startPoint
和endPoint
的變化范圍而言的哑了。看到這赘方,你一定會說,這個玩意有什么卵用弱左。
下面找一個之前寫過的一個Demo窄陡,簡單的彩色進(jìn)度條:
//CAGradientLayer
-(void)creatGradientLayer{
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.bounds = CGRectMake(0, 0, 220, 220);
gradientLayer.position = self.view.center;
[self.view.layer addSublayer:gradientLayer];
//
NSMutableArray *colorArray = [NSMutableArray new];
for (NSInteger hue = 0; hue <= 360; hue += 5) {
UIColor *color = [UIColor colorWithHue:1.0*hue/360.0
saturation:1.0
brightness:1.0
alpha:1.0];
[colorArray addObject:(id)color.CGColor];
}
//
gradientLayer.colors = colorArray;
//gradientLayer.locations = @[@(0.3),@(0.7)];
//
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
//ShapeLayer
UIBezierPath *bezierP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(10, 10, 200, 200)];
CAShapeLayer* shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.path = bezierP.CGPath;
shapeLayer.lineWidth = 10;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [UIColor blueColor].CGColor;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.strokeStart = 0;
shapeLayer.strokeEnd = 0;
gradientLayer.mask = shapeLayer;
//
NSTimeInterval delayTime = 1.0f;
NSTimeInterval timeInterval = 0.5f;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_time_t startDelayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC));
dispatch_source_set_timer(_timer, startDelayTime, timeInterval * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(_timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (shapeLayer.strokeEnd < 0.6) {
shapeLayer.strokeEnd += 0.4;
}else if (shapeLayer.strokeEnd < 0.8){
shapeLayer.strokeEnd += 0.2;
}else if (shapeLayer.strokeEnd < 1){
shapeLayer.strokeEnd += 0.1;
}else{
dispatch_source_cancel(_timer);
}
});
});
dispatch_resume(_timer);
}
CAEmitterLayer
CAEmitterLayer,他的屬性真的是看的讓人生無可戀拆火,就算你這個字段什么意思跳夭,寫出你想要的效果也需要一個大量的調(diào)整的過程,簡直爆炸们镜。之前寫了一個雨夾雪币叹,供大家參考。
#pragma mark CAEmitterLayer && CAEmitterCell
/*
CAEmitterLayer 屬性介紹
birthRate:粒子產(chǎn)生系數(shù)模狭,默認(rèn)1.0颈抚;
emitterCells: 裝著CAEmitterCell對象的數(shù)組,被用于把粒子投放到layer上嚼鹉;
emitterDepth:決定粒子形狀的深度聯(lián)系:emittershape
emitterMode:發(fā)射模式
NSString * const kCAEmitterLayerPoints;
NSString * const kCAEmitterLayerOutline;
NSString * const kCAEmitterLayerSurface;
NSString * const kCAEmitterLayerVolume;
emitterPosition:發(fā)射位置
emitterShape:發(fā)射源的形狀:
NSString * const kCAEmitterLayerPoint;
NSString * const kCAEmitterLayerLine;
NSString * const kCAEmitterLayerRectangle;
NSString * const kCAEmitterLayerCuboid;
NSString * const kCAEmitterLayerCircle;
NSString * const kCAEmitterLayerSphere;
emitterSize:發(fā)射源的尺寸大贩汉;
emitterZposition:發(fā)射源的z坐標(biāo)位置;
lifetime:粒子生命周期
preservesDepth:不是多很清楚(粒子是平展在層上)
renderMode:渲染模式:
NSString * const kCAEmitterLayerUnordered;
NSString * const kCAEmitterLayerOldestFirst;
NSString * const kCAEmitterLayerOldestLast;
NSString * const kCAEmitterLayerBackToFront;
NSString * const kCAEmitterLayerAdditive;
scale:粒子的縮放比例:
seed:用于初始化隨機(jī)數(shù)產(chǎn)生的種子
spin:自旋轉(zhuǎn)速度
velocity:粒子速度
*/
- (void)startCAEmitterLayer {
// EmitterLayer
CGRect showRect = self.view.bounds;
UIView *view = [[UIView alloc] initWithFrame:showRect];
view.backgroundColor = [UIColor blackColor];
[self.view addSubview:view];
self.emitterLayer = [CAEmitterLayer layer];
self.emitterLayer.frame = view.bounds;
self.emitterLayer.masksToBounds = YES;
self.emitterLayer.emitterShape = kCAEmitterLayerLine;
self.emitterLayer.emitterMode = kCAEmitterLayerSurface;
self.emitterLayer.emitterSize = showRect.size;
self.emitterLayer.emitterPosition = CGPointMake(showRect.size.width / 2.f, - 20);
[self setEmitterCell];
[view.layer addSublayer:self.emitterLayer];
}
/*
CAEmitterCell 屬性介紹
CAEmitterCell類代表從CAEmitterLayer射出的粒子锚赤;emitter cell定義了粒子發(fā)射的方向匹舞。
alphaRange: 一個粒子的顏色alpha能改變的范圍;
alphaSpeed:粒子透明度在生命周期內(nèi)的改變速度线脚;
birthrate:粒子參數(shù)的速度乘數(shù)因子赐稽;每秒發(fā)射的粒子數(shù)量
blueRange:一個粒子的顏色blue 能改變的范圍;
blueSpeed: 粒子blue在生命周期內(nèi)的改變速度浑侥;
color:粒子的顏色
contents:是個CGImageRef的對象,既粒子要展現(xiàn)的圖片姊舵;
contentsRect:應(yīng)該畫在contents里的子rectangle:
emissionLatitude:發(fā)射的z軸方向的角度
emissionLongitude:x-y平面的發(fā)射方向
emissionRange;周圍發(fā)射角度
emitterCells:粒子發(fā)射的粒子
enabled:粒子是否被渲染
greenrange: 一個粒子的顏色green 能改變的范圍寓落;
greenSpeed: 粒子green在生命周期內(nèi)的改變速度蠢莺;
lifetime:生命周期
lifetimeRange:生命周期范圍 lifetime= lifetime(+/-) lifetimeRange
magnificationFilter:不是很清楚好像增加自己的大小
minificatonFilter:減小自己的大小
minificationFilterBias:減小大小的因子
name:粒子的名字
redRange:一個粒子的顏色red 能改變的范圍;
redSpeed; 粒子red在生命周期內(nèi)的改變速度零如;
scale:縮放比例:
scaleRange:縮放比例范圍;
scaleSpeed:縮放比例速度:
spin:子旋轉(zhuǎn)角度
spinrange:子旋轉(zhuǎn)角度范圍
style:不是很清楚:
velocity:速度
velocityRange:速度范圍
xAcceleration:粒子x方向的加速度分量
yAcceleration:粒子y方向的加速度分量
zAcceleration:粒子z方向的加速度分量
emitterCells:粒子發(fā)射的粒子
注意:粒子同樣有emitterCells屬性锄弱,也就是說粒子同樣可以發(fā)射粒子考蕾。
*/
- (void)setEmitterCell {
CAEmitterCell *rainflake = [CAEmitterCell emitterCell];
rainflake.birthRate = 5.f;
rainflake.speed = 10.f;
rainflake.velocity = 10.f;
rainflake.velocityRange = 10.f;
rainflake.yAcceleration = 1000.f;
rainflake.contents = (__bridge id)([UIImage imageNamed:@"rain.png"].CGImage);
rainflake.color = [UIColor whiteColor].CGColor;
rainflake.lifetime = 160.f;
rainflake.scale = 0.2f;
rainflake.scaleRange = 0.f;
CAEmitterCell *snowflake = [CAEmitterCell emitterCell];
snowflake.birthRate = 1.f;
snowflake.speed = 10.f;
snowflake.velocity = 2.f;
snowflake.velocityRange = 10.f;
snowflake.yAcceleration = 10.f;
snowflake.emissionRange = 0.5 * M_PI;
snowflake.spinRange = 0.25 * M_PI;
snowflake.contents = (__bridge id)([UIImage imageNamed:@"snow.png"].CGImage);
snowflake.color = [UIColor cyanColor].CGColor;
snowflake.lifetime = 160.f;
snowflake.scale = 0.5;
snowflake.scaleRange = 0.3;
//添加到EmitterLayer中
self.emitterLayer.emitterCells = @[snowflake,rainflake];
}
運(yùn)行效果:
剩下的那些CALayer的子類,正好我有空会宪,如果你也有空肖卧,來這里,我說掸鹅,你聽塞帐,CALayer這些牛逼的子類你造嗎_補(bǔ)全篇拦赠。