1. 程式人生 > >IOS CALayer的屬性和使用

IOS CALayer的屬性和使用

一、CALayer的常用屬性

  • 1、@propertyCGPoint position; 
    圖層中心點的位置,類似與UIView的center;用來設定CALayer在父層中的位置;以父層的左上角為原點(0,0);

  • 2、 @property CGPoint anchorPoint; 
    稱『定位點』、『錨點』,該描述是相對於x、y位置比例而言的預設在影象中心點(0.5、0.5)的位置;決定著CALayer身上的哪個點會再position屬性所指的位置,以自己的左上角為原點(0,0);它的x、y取值範圍都是0~1。

  • 3、 @property(nullable) CGColorRef backgroundColor; 
    圖層背景顏色

  • 4、 @property(nullable) CGColorRef borderColor; 
    圖層邊框顏色

  • 5、 @property CGFloat borderWidth; 
    圖層邊框寬度

  • 6、 @property CGRect bounds; 
    圖層大小

  • 7、 @property(nullable, strong) id contents; 
    圖層顯示內容,例如可以將圖片作為圖層內容顯示

  • 8、 @property CGRect contentsRect; 
    圖層顯示內容的大小和位置

  • 9、 @property CGFloat cornerRadius; 
    圓角半徑

  • 10、 @property(getter=isDoubleSided) BOOL doubleSided; 
    圖層背景是否顯示,預設是YES

  • 11、 @property CGRect frame; 
    圖層大小和位置,不支援隱式動畫,所以CALyaer中很少使用frame,通常使用bound和position代替

  • 12、 @property(getter=isHidden) BOOL hidden; 
    是否隱藏

  • 13、 @property(nullable, strong) CALayer *mask; 
    圖層蒙版

  • 14、 @property BOOL masksToBounds; 
    子圖層是否剪下圖層邊界,預設是NO

  • 15、 @property float opacity; 
    圖層透明度,類似與UIView的alpha

  • 16、 @property(nullable) CGColorRef shadowColor; 
    陰影顏色

  • 17、 @property CGSize shadowOffset; 
    陰影偏移量

  • 18、 @property float shadowOpacity; 
    陰影透明度,注意預設為0,如果設定陰影必須設定此屬性

  • 19、 @property(nullable) CGPathRef shadowPath; 
    陰影形狀

  • 20、 @property CGFloat shadowRadius; 
    陰影模糊半徑

  • 21、 @property(nullable, copy) NSArray

二、CALayer不常用屬性

  • 1、 @property CGFloat zPosition; 
    圖層中心點在z軸中的位置

  • 2、 @property CGFloat anchorPointZ; 
    圖層在z軸中的錨點;

  • 3、 - (CGAffineTransform)affineTransform;

  • 4、- (void)setAffineTransform:(CGAffineTransform)m; 
    以上屬性為圖層形變;該屬性值指定一個CGAffineTransform物件,該物件代表對CALayer執行X、Y兩個維度(也就是平面)上的旋轉、縮放、位移、斜切、映象等變換矩陣

  • 5、 @property(nullable, readonly) CALayer *superlayer; 
    圖層的父圖層

三、CALayer圖層操作

  • 1、 - (void)addSublayer:(CALayer *)layer; 
    新增子圖層

  • 2、 - (void)removeFromSuperlayer; 
    將自己從父圖層中移除

  • 3、 - (void)insertSublayer:(CALayer *)layer atIndex:(unsigned)idx; 
    在自己子圖層陣列中的第idx位置新增圖層

  • 4、 - (void)insertSublayer:(CALayer )layer below:(nullable CALayer )sibling; 
    將圖層layer新增在子圖層sibling的下面

  • 5、 - (void)insertSublayer:(CALayer )layer above:(nullable CALayer )sibling; 
    將圖層layer新增在子圖層sibling的上面

  • 6、 - (void)replaceSublayer:(CALayer )layer with:(CALayer )layer2; 
    將圖層layer替換layer2;

四、CALayer動畫操作

  • 1、 - (void)addAnimation:(CAAnimation )anim forKey:(nullable NSString )key; 
    圖層新增某一屬性的動畫

  • 2、 - (nullable NSArray< NSString )animationKeys; 
    獲取所有動畫的屬性

  • 3、 - (nullable CAAnimation )animationForKey:(NSString )key; 
    獲取某一屬性的動畫

  • 4、 - (void)removeAnimationForKey:(NSString *)key; 
    移除某一屬性動畫

  • 5、 - (void)removeAllAnimations; 
    移除所有動畫

五、隱式動畫

ios中CALayer的設計主要是為了內容展示和動畫操作,CALayer本身並不包含在UIKit中,它不能響應事件。由於CALayer在設計之初就考慮它的動畫操作功能,CALayer很多屬性在修改時都能形成動畫效果,這種屬性稱為『隱式動畫屬性』。但是對於UIView的根檢視層而言屬性的修改並不形成動畫效果,因為很多情況下根圖層更多的充當容器的作用,如果它的屬性變動形成動畫效果會直接影響子圖層。另外,UIView的根圖層建立工作完全有iOS負責完成,無法重新建立,但是可以往根圖層中新增子圖層或移除子圖層。

    • 1、如何檢視CALayer的某個屬性是否支援隱式動畫

      • 可以檢視標頭檔案,看有沒有Animatable,如果有表示支援; 
        這裡寫圖片描述
      • 檢視官方文件
      • 這裡寫圖片描述 
      • 下面標明都支援隱式動畫
      • 這裡寫圖片描述
    • 2、例子

#pragma mark 繪製圖層
-(void)drawMyLayer{
    CGSize size=[UIScreen mainScreen].bounds.size;
    //獲得根圖層
    layer=[[CALayer alloc]init];
    //設定背景顏色,由於QuartzCore是跨平臺框架,無法直接使用UIColor
    layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
    //設定中心點
    layer.position=CGPointMake(size.width/2, size.height/2);
    //設定大小
    layer.bounds=CGRectMake(0, 0, WIDTH,WIDTH);
    //設定圓角,當圓角半徑等於矩形的一半時看起來就是一個圓形
    layer.cornerRadius=WIDTH/2;
    //設定陰影
    layer.shadowColor=[UIColor grayColor].CGColor;
    layer.shadowOffset=CGSizeMake(2, 2);
    layer.shadowOpacity=.9;
    //設定邊框
    //    layer.borderColor=[UIColor whiteColor].CGColor;
    //    layer.borderWidth=1;
    //設定錨點
    //    layer.anchorPoint=CGPointZero;
    [self.view.layer addSublayer:layer];
}
#pragma mark 點選放大
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch=[touches anyObject];
    CGFloat width=layer.bounds.size.width;
    if (width==WIDTH) {
        width=WIDTH*4;
    }else{
        width=WIDTH;
    }
    layer.bounds=CGRectMake(0, 0, width, width);
    layer.position=[touch locationInView:self.view];
    layer.cornerRadius=width/2;
}

這裡寫圖片描述

七、CALayer繪圖

使用Quartz 2D繪圖,是直接呼叫UIView的drawRect:方法繪製圖形、影象,這種方式的本質還是再圖層中繪製。drawRect:方法是由UIKit元件進行呼叫,因此釐米那可以使用到一些UIKir封裝的方法進行繪製,而直接繪製到圖層的方法由於並非UIKit直接呼叫因此只能用原生的Core Graphics方法繪製; 
圖層繪製有兩種方法,不管使用那種方法繪製完必須呼叫圖層的setNeedDisplay方法,下面介紹圖層的兩種繪製方法:

(1)、通過圖層代理drawLayer:inContext:方法繪製

通過代理方法進行圖層呢個繪製只要指定圖層的代理,然後在代理物件中重寫 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;方法即可。需要注意這個方法雖然是代理方法但是不用手動實習那CALayerDelegate,因為CALayer定義中給NSObject做了分類擴充套件,所有的NSObject都包含這個方法。另外設定完代理後必須要呼叫圖層的 - (void)setNeedsDisplay;方法,否測繪製內容無法顯示; 
例如:

#pragma mark 繪製圖層
-(void)drawMyLayer{
    //自定義圖層
    CALayer *layer=[[CALayer alloc]init];
    layer.bounds=CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
    layer.position=CGPointMake(160, 200);
    layer.backgroundColor=[UIColor redColor].CGColor;
    layer.cornerRadius=PHOTO_HEIGHT/2;
    //注意僅僅設定圓角,對於圖形而言可以正常顯示,但是對於圖層中繪製的圖片無法正確顯示
    //如果想要正確顯示則必須設定masksToBounds=YES,剪下子圖層
    layer.masksToBounds=YES;
    //陰影效果無法和masksToBounds同時使用,因為masksToBounds的目的就是剪下外邊框,
    //而陰影效果剛好在外邊框
    //    layer.shadowColor=[UIColor grayColor].CGColor;
    //    layer.shadowOffset=CGSizeMake(2, 2);
    //    layer.shadowOpacity=1;
    //設定邊框
    layer.borderColor=[UIColor whiteColor].CGColor;
    layer.borderWidth=2;
    //設定圖層代理
    layer.delegate=self;
    //新增圖層到根圖層
    [self.view.layer addSublayer:layer];
    //呼叫圖層setNeedDisplay,否則代理方法不會被呼叫
    [layer setNeedsDisplay];
}
#pragma mark 繪製圖形、影象到圖層,注意引數中的ctx是圖層的圖形上下文,其中繪圖位置也是相對圖層而言的
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    //    NSLog(@"%@",layer);//這個圖層正是上面定義的圖層
    CGContextSaveGState(ctx);
    //圖形上下文形變,解決圖片倒立的問題
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -PHOTO_HEIGHT);
    UIImage *image=[UIImage imageNamed:@"001.png"];
    //注意這個位置是相對於圖層而言的不是螢幕
    CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage);
    //    CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
    //    CGContextDrawPath(ctx, kCGPathFillStroke);
    CGContextRestoreGState(ctx);
}

(2)、使用自定義圖層繪圖

在自定義圖層繪圖時只要自己編寫一個類繼承與CALayer然後在 - (void)drawInContext:(CGContextRef)ctx;中繪圖即可。同前面在代理方法繪圖一樣,要顯示圖層中繪製的內容也要呼叫圖層的 - (void)setNeedsDisplay;方法,否則 - (void)drawInContext:(CGContextRef)ctx;方法將不會呼叫; 
例如: 

KCALayer.h
#import "KCALayer.h"

@implementation KCALayer
-(void)drawInContext:(CGContextRef)ctx{
    NSLog(@"3-drawInContext:");
    NSLog(@"CGContext:%@",ctx);
    //    CGContextRotateCTM(ctx, M_PI_4);
    CGContextSetRGBFillColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1);
    CGContextSetRGBStrokeColor(ctx, 135.0/255.0, 232.0/255.0, 84.0/255.0, 1);
    //    CGContextFillRect(ctx, CGRectMake(0, 0, 100, 100));
    //    CGContextFillEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));
    CGContextMoveToPoint(ctx, 94.5, 33.5);
    //// Star Drawing
    CGContextAddLineToPoint(ctx,104.02, 47.39);
    CGContextAddLineToPoint(ctx,120.18, 52.16);
    CGContextAddLineToPoint(ctx,109.91, 65.51);
    CGContextAddLineToPoint(ctx,110.37, 82.34);
    CGContextAddLineToPoint(ctx,94.5, 76.7);
    CGContextAddLineToPoint(ctx,78.63, 82.34);
    CGContextAddLineToPoint(ctx,79.09, 65.51);
    CGContextAddLineToPoint(ctx,68.82, 52.16);
    CGContextAddLineToPoint(ctx,84.98, 47.39);
    CGContextClosePath(ctx);
    CGContextDrawPath(ctx, kCGPathFillStroke);
}
@end
ViewController.m
#pragma mark 繪製圖層
-(void)drawMyLayer{
    KCALayer *layer=[[KCALayer alloc]init];
    layer.bounds=CGRectMake(0, 0, 185, 185);
    layer.position=CGPointMake(160,284);
    layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
    //顯示圖層
    [layer setNeedsDisplay];
    [self.view.layer addSublayer:layer];
}

 

這裡寫圖片描述

七、CALayer繪圖

使用Quartz 2D繪圖,是直接呼叫UIView的drawRect:方法繪製圖形、影象,這種方式的本質還是再圖層中繪製。drawRect:方法是由UIKit元件進行呼叫,因此釐米那可以使用到一些UIKir封裝的方法進行繪製,而直接繪製到圖層的方法由於並非UIKit直接呼叫因此只能用原生的Core Graphics方法繪製; 
圖層繪製有兩種方法,不管使用那種方法繪製完必須呼叫圖層的setNeedDisplay方法,下面介紹圖層的兩種繪製方法:

(1)、通過圖層代理drawLayer:inContext:方法繪製

通過代理方法進行圖層呢個繪製只要指定圖層的代理,然後在代理物件中重寫 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;方法即可。需要注意這個方法雖然是代理方法但是不用手動實習那CALayerDelegate,因為CALayer定義中給NSObject做了分類擴充套件,所有的NSObject都包含這個方法。另外設定完代理後必須要呼叫圖層的 - (void)setNeedsDisplay;方法,否測繪製內容無法顯示; 
例如: