之前說到貝塞爾曲線,今天說CALayer,哈哈哈,承上啟下,放一個表情與上一篇相呼應。
CALayer
首先,CALayer其實自身有很多情況下自帶隱式動畫,但是需要注意的是UIView的根Layer是沒有隱式動畫的。下面看一下CALayer的幾個重要的屬性:
對于大多數(shù)開發(fā)者老說,CALayer是很熟悉的一個名詞,但是對于它的屬性可能一知半解,上表大致說明了CALayer的幾個重要屬性的作用以及是否支持隱式動畫,下面著重介紹幾個點:
(1)frame屬性
frame不支持隱式動畫,所以通常使用bounds和position來設(shè)置layer的位置和大小
(2)contents
設(shè)置layer的contents可以為layer添加顯示內(nèi)容,最直接的便是將UIImage轉(zhuǎn)化為CGImageRef賦值,其與backgroundColor的關(guān)系就相當于UIImageView的image和backgorundColor的關(guān)系。
(3)錨點 anchorPoint
錨點的取值范圍為(0~1,0~1),標示此點相對于寬高的比例,默認點(0.5,0.5),錨點的位置對圖層的位置以及某些動畫的重心起到?jīng)Q定性的作用,通過錨點計算圖層位置-->中心點相對于父父層的位置永遠不變,錨點于中心點重合。以旋轉(zhuǎn)動畫為例,錨點是旋轉(zhuǎn)的中心。
(4)mask
mask的作用就相當于PS中的蒙版,在一些圖層處理上具有很大的優(yōu)勢(注:蒙版透明色為過濾掉指定layer的區(qū)域內(nèi)容,不透明色為顯示制定圖層的區(qū)域內(nèi)容)
CALayer的子類
CALayer的子類有很多,下面說幾個比較常用的:
CAShapeLayer
看一下CAShapeLayer相對于CALayer多出來的屬性:
path
CAShapeLayer的path屬性是他如此牛逼的一個重要起點,也是它和貝塞爾曲線緊密連接一個入口,他決定了我們要在圖層上畫一個什么形狀。(注:當與貝塞爾曲線一起使用的時候,生成的曲線的位置是相對于生成的layer的,所以當你利用貝塞爾曲線設(shè)置了path后,再設(shè)置layer的position和bounds你會感覺很奇怪,最簡單的方式就是單純利用貝塞爾曲線決定圖層的位置和大?。?/p>
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)部” 是很直觀清除的。但是,對一個復雜的路徑,比如自相交或者一個子路徑包圍另一個子路徑,“內(nèi)部”的理解就不那么明了。
fillRule提供兩種選項用于指定如何判斷圖形的內(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];
}
當fillRule為kCAFillRuleNonZero
時:
當fillRule為
kCAFillRuleEvenOdd
時:通過上面的代碼再加上下面抄襲的描述,應該能夠相當清晰的理解這其中的意義。
kCAFillRuleNonZero
字面意思是“非零”。按該規(guī)則,要判斷一個點是否在圖形內(nèi),從該點作任意方向的一條射線,然后檢測射線與圖形路徑的交點情況。從0開始計數(shù),路徑從左向右穿過射線則計數(shù)加1,從右向左穿過射線則計數(shù)減1。得出計數(shù)結(jié)果后,如果結(jié)果是0,則認為點在圖形外部,否則認為在內(nèi)部。下圖演示了kCAFillRuleNonZero規(guī)則 :
kCAFillRuleEvenOdd
字面意思是“奇偶”。按該規(guī)則,要判斷一個點是否在圖形內(nèi),從該點作任意方向的一條射線,然后檢測射線與圖形路徑的交點的數(shù)量。如果結(jié)果是奇數(shù)則認為點在內(nèi)部,是偶數(shù)則認為點在外部。下圖演示了kCAFillRuleEvenOdd 規(guī)則:
strokeColor
線顏色
strokeStart strokeEnd
兩者的取值都是0~1,決定貝塞爾曲線的劃線百分比,對應值的改變支持隱式動畫。
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];
運行結(jié)果:
lineWidth
線寬
miterLimit
最大斜接長度,只有l(wèi)ineJoin屬性為kCALineJoinMiter時miterLimit才有效,當銜接角度太小時,斜接長度就會很大,如果設(shè)置了 miterLimit
并且當斜接長度大于這個值時,便會對應裁切掉多余區(qū)域:
設(shè)置
miterLimit
后:lineCap
線端點類型,也就是對應曲線結(jié)束的點的顯示樣式。
lineJoin
連接點類型,也就是對應曲線節(jié)點的位置的顯示樣式。
lineDashPattern
虛線設(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)建子線程隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//使用之前創(chuàng)建的隊列來創(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);
效果如圖:(視頻好像有點快...)
其實CAShapeLayer的用處很多,能實現(xiàn)很多動畫效果的同時,也可以實現(xiàn)很多蒙版效果,心有多大,功能就有多大。
之前寫過一個點擊擴散的庫,主要用到蒙版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
效果如下:
另外,其實我們看到的很多酷炫的變幻莫測的動畫很多都是CAShapeLayer
或者Quartz 2D
繪圖配合幀率刷新的結(jié)果。來,有時間我給你講講啊。
CAGradientLayer
下面再說一個比較常用的子類CAGradientLayer
,我們一般使用它生成平滑的顏色過渡。大致的效果如下:
同樣,我們還是從它的特有屬性入手:
colors
在Layer中現(xiàn)實的幾種顏色并完成完美過渡,和CAShapeLayer
的path
一樣,colors
是CAGradientLayer
特殊屬性的起點,也就是x 顯示的要素。
locations
顏色區(qū)間分布比例,默認為線性均勻分布。取值范圍為0~1遞增,一般來說其中的元素個數(shù)應與colors中的元素個數(shù)相同,不同時系統(tǒng)會自行處理分布規(guī)則。
設(shè)置 gradientLayer.locations = @[@(0.3),@(0.7)];
startPoint endPoint
startPoint
決定了變色范圍的起始點,endPoint
決定了變色范圍的結(jié)束點,兩者的連線決定變色的趨勢:
注意:
locations
是相對于startPoint
和endPoint
的變化范圍而言的。看到這,你一定會說,這個玩意有什么卵用。
下面找一個之前寫過的一個Demo,簡單的彩色進度條:
//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ù),默認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坐標位置;
lifetime:粒子生命周期
preservesDepth:不是多很清楚(粒子是平展在層上)
renderMode:渲染模式:
NSString * const kCAEmitterLayerUnordered;
NSString * const kCAEmitterLayerOldestFirst;
NSString * const kCAEmitterLayerOldestLast;
NSString * const kCAEmitterLayerBackToFront;
NSString * const kCAEmitterLayerAdditive;
scale:粒子的縮放比例:
seed:用于初始化隨機數(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:應該畫在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];
}
運行效果:
剩下的那些CALayer的子類,正好我有空,如果你也有空,來這里,我說,你聽,CALayer這些牛逼的子類你造嗎_補全篇。