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

之前說到貝塞爾曲線,今天說CALayer,哈哈哈,承上啟下,放一個表情與上一篇相呼應。

CALayer

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


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

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

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)實的幾種顏色并完成完美過渡,和CAShapeLayerpath一樣,colorsCAGradientLayer特殊屬性的起點,也就是x 顯示的要素。

locations

顏色區(qū)間分布比例,默認為線性均勻分布。取值范圍為0~1遞增,一般來說其中的元素個數(shù)應與colors中的元素個數(shù)相同,不同時系統(tǒng)會自行處理分布規(guī)則。
設(shè)置 gradientLayer.locations = @[@(0.3),@(0.7)];

startPoint endPoint

startPoint決定了變色范圍的起始點,endPoint決定了變色范圍的結(jié)束點,兩者的連線決定變色的趨勢:

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,簡單的彩色進度條:

//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);
}
運行結(jié)果

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這些牛逼的子類你造嗎_補全篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

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

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,543評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,131評論 5 13
  • 目錄: 主要繪圖框架介紹 CALayer 繪圖 貝塞爾曲線-UIBezierPath CALayer子類 補充:i...
    Ryan___閱讀 1,689評論 1 9
  • Core Animation Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,...
    45b645c5912e閱讀 3,047評論 0 21
  • 有一天醒了,突發(fā)奇想做了一個問卷,我稱之為<枝樓 · 奇跡問卷>。感謝這個回答認真的匿名者。 一、嬰兒問卷【嬰兒時...
    枝樓閱讀 330評論 0 1