iOS動畫篇_CALayer這些牛逼的子類你造嗎

之前說到貝塞爾曲線,今天說CALayer恶座,哈哈哈,承上啟下沥阳,放一個表情與上一篇相呼應(yīng)跨琳。

CALayer

首先,CALayer其實(shí)自身有很多情況下自帶隱式動畫桐罕,但是需要注意的是UIView的根Layer是沒有隱式動畫的脉让。下面看一下CALayer的幾個重要的屬性:


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子類圖解

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時:

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í)的幾種顏色并完成完美過渡,和CAShapeLayerpath一樣第晰,colorsCAGradientLayer特殊屬性的起點(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)纺非,兩者的連線決定變色的趨勢:

gradientLayer.startPoint = CGPointMake(0, 0); gradientLayer.endPoint = CGPointMake(1, 1);

gradientLayer.startPoint = CGPointMake(0.5, 0); gradientLayer.endPoint = CGPointMake(1, 1);
gradientLayer.startPoint = CGPointMake(0, 0.5); gradientLayer.endPoint = CGPointMake(1, 1);

gradientLayer.locations = @[@(0.3),@(0.7)]; // gradientLayer.startPoint = CGPointMake(0, 0); gradientLayer.endPoint = CGPointMake(0.5, 0.5);

注意:locations是相對于startPointendPoint的變化范圍而言的哑了。
看到這赘方,你一定會說,這個玩意有什么卵用弱左。

下面找一個之前寫過的一個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);
}
運(yùn)行結(jié)果

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ǔ)全篇拦赠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市葵姥,隨后出現(xiàn)的幾起案子荷鼠,更是在濱河造成了極大的恐慌,老刑警劉巖榔幸,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件允乐,死亡現(xiàn)場離奇詭異,居然都是意外死亡削咆,警方通過查閱死者的電腦和手機(jī)牍疏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拨齐,“玉大人鳞陨,你說我怎么就攤上這事≌巴铮” “怎么了厦滤?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長熟史。 經(jīng)常有香客問我馁害,道長,這世上最難降的妖魔是什么蹂匹? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任碘菜,我火速辦了婚禮,結(jié)果婚禮上限寞,老公的妹妹穿的比我還像新娘忍啸。我一直安慰自己,他們只是感情好履植,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布计雌。 她就那樣靜靜地躺著,像睡著了一般玫霎。 火紅的嫁衣襯著肌膚如雪凿滤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天庶近,我揣著相機(jī)與錄音翁脆,去河邊找鬼。 笑死鼻种,一個胖子當(dāng)著我的面吹牛反番,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼罢缸,長吁一口氣:“原來是場噩夢啊……” “哼篙贸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起枫疆,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤爵川,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后养铸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雁芙,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年钞螟,在試婚紗的時候發(fā)現(xiàn)自己被綠了兔甘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鳞滨,死狀恐怖洞焙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拯啦,我是刑警寧澤澡匪,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站褒链,受9級特大地震影響唁情,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甫匹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一甸鸟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兵迅,春花似錦抢韭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扯夭,卻和暖如春鳍贾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背交洗。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工贾漏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藕筋。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親隐圾。 傳聞我的和親對象是個殘疾皇子伍掀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜暇藏,今天將帶大家一窺ios動畫全貌蜜笤。在這里你可以看...
    每天刷兩次牙閱讀 8,488評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜盐碱,今天將帶大家一窺iOS動畫全貌把兔。在這里你可以看...
    F麥子閱讀 5,110評論 5 13
  • 目錄: 主要繪圖框架介紹 CALayer 繪圖 貝塞爾曲線-UIBezierPath CALayer子類 補(bǔ)充:i...
    Ryan___閱讀 1,673評論 1 9
  • Core Animation Core Animation,中文翻譯為核心動畫瓮顽,它是一組非常強(qiáng)大的動畫處理API县好,...
    45b645c5912e閱讀 3,028評論 0 21
  • 有一天醒了,突發(fā)奇想做了一個問卷暖混,我稱之為<枝樓 · 奇跡問卷>缕贡。感謝這個回答認(rèn)真的匿名者。 一拣播、嬰兒問卷【嬰兒時...
    枝樓閱讀 320評論 0 1