CALayer
當(dāng)利用drawRect
:方法繪圖的本質(zhì)就是繪制到了UIView
的layer
(屬性)中。
CALayer
很多屬性在修改時(shí)都能形成動(dòng)畫效果芽世,這種屬性稱為“隱式動(dòng)畫屬性”扮念。但是對(duì)于UIView
的根圖層而言屬性的修改并不形成動(dòng)畫效果担敌,因?yàn)楹芏嗲闆r下根圖層更多的充當(dāng)容器的做用檀何。并且UIView
的根圖層創(chuàng)建工作完全由iOS負(fù)責(zé)完成重虑,無法重新創(chuàng)建践付。
直接在圖層中繪圖
當(dāng)時(shí)調(diào)用了UIView
的drawRect:
方法繪制圖形、圖像缺厉,這種方式本質(zhì)還是在圖層中繪制永高。只是drawRect:
方法是由UIKit
組件進(jìn)行調(diào)用,因此里面可以使用一些UIKit
封裝的方法進(jìn)行繪圖提针,而直接繪制到圖層的方法由于并非UIKit
直接調(diào)用因此只能用原生的Core Graphics
方法繪制命爬。
CALayer
圖層內(nèi)部繪圖有兩個(gè)方法:(都需要調(diào)用setNeedDisplay
方法)
- 通過圖層代理繪制 (CALayerDelegate)
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx; - 通過自定義圖層繪制 (CALayer)
- (void)drawInContext:(CGContextRef)ctx;
使用圖層代理繪圖
只要指定某圖層(CALayer
)的代理,然后在代理對(duì)象中重寫-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
方法辐脖。這里不需要手動(dòng)實(shí)現(xiàn)CALayerDelegate
饲宛,因?yàn)?code>CALayer定義中給NSObject
做了分類擴(kuò)展,所有的NSObject
都包含這個(gè)方法嗜价。
//
// ViewController.m
// CartoonLearn
//
// Created by xiaodoubaba on 16/2/1.
// Copyright ? 2016年 xiaodoubaba. All rights reserved.
//
#import "ViewController.h"
#define Photo_Height 150
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGPoint position = CGPointMake(160, 200);
CGRect bounds = CGRectMake(0, 0, Photo_Height, Photo_Height);
CGFloat cornerRadius = Photo_Height / 2;
CGFloat borderWidth = 2;
//陰影圖層
CALayer *layerShadow = [[CALayer alloc]init];
layerShadow.bounds = bounds;
layerShadow.position = position;
layerShadow.cornerRadius = cornerRadius;
layerShadow.shadowColor = [UIColor grayColor].CGColor;
layerShadow.shadowOffset = CGSizeMake(2, 1);
layerShadow.shadowOpacity = 1;
layerShadow.borderColor = [UIColor whiteColor].CGColor;
layerShadow.borderWidth = borderWidth;
[self.view.layer addSublayer:layerShadow];
//容器圖層
CALayer *layer = [[CALayer alloc] init];
layer.bounds = bounds;
layer.position = position;
layer.backgroundColor = [UIColor orangeColor].CGColor;
layer.cornerRadius = cornerRadius;
//子圖層是否剪切圖層邊界艇抠,默認(rèn)為NO
layer.masksToBounds = YES;
/*陰影效果無法和masksToBounds同時(shí)使用,因?yàn)閙asksToBounds的目的就是剪切外邊框久锥,
而陰影效果剛好在外邊框
換個(gè)思路:使用兩個(gè)大小一樣的圖層家淤,下面的圖層負(fù)責(zé)繪制陰影,上面的圖層用來顯示圖片瑟由。
layer.shadowColor=[UIColor grayColor].CGColor;
layer.shadowOffset=CGSizeMake(2, 2);
layer.shadowOpacity=1;
*/
layer.borderColor = [UIColor grayColor].CGColor;
layer.borderWidth = 2;
/*利用圖層形變解決圖像倒立問題
在動(dòng)畫開發(fā)中形變往往不是直接設(shè)置transform絮重,而是通過keyPath進(jìn)行設(shè)置。
這種方法設(shè)置形變的本質(zhì)沒有區(qū)別,只是利用了KVC可以動(dòng)態(tài)修改其屬性值而已青伤。
下面的代碼可以替換為:
[layer setValue:@M_PI forKeyPath:@"transform.rotation.x"];
*/
layer.transform=CATransform3DMakeRotation(M_PI, 1, 0, 0);
/*如果僅僅就顯示一張圖片在圖層中督怜,直接設(shè)置圖層contents就可以了。無需delegate
UIImage *image = [UIImage imageNamed:@"picture"];
layer.contents = (id)image.CGImage;
[layer setContents:(id)image.CGImage];
*/
layer.delegate = self;
[self.view.layer addSublayer:layer];
//調(diào)用圖層setNeedDisplay,否則代理方法不會(huì)被調(diào)用
[layer setNeedsDisplay];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
/*如果沒有設(shè)置layer.transform,需要加上
CGContextSaveGState(ctx);
//圖形上下文形變潮模,解決圖片倒立的問題
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -Photo_Height);
*/
UIImage *image = [UIImage imageNamed:@"picture"];
//相對(duì)于圖層位置,不是屏幕
CGContextDrawImage(ctx, CGRectMake(0, 0, Photo_Height, Photo_Height), image.CGImage);
/*如果沒有設(shè)置layer.transform,需要加上
CGContextRestoreGState(ctx);
*/
}
@end
圖層代理繪圖.png
使用自定義圖層繪圖
編寫一個(gè)類繼承于
CALayer
然后在drawInContext:
中使用CGContext
繪圖亮蛔。同樣需要調(diào)用setNeedDisplay方法。
//
// XDLayer.m
// CartoonLearn
//
// Created by xiaodoubaba on 16/2/2.
// Copyright ? 2016年 xiaodoubaba. All rights reserved.
//
#import "XDLayer.h"
@implementation XDLayer
- (void)drawInContext:(CGContextRef)ctx
{
NSLog(@"3-drawInContext:");
NSLog(@"CGContext:%@",ctx);
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);
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
//
// XDView.m
// CartoonLearn
//
// Created by xiaodoubaba on 16/2/2.
// Copyright ? 2016年 xiaodoubaba. All rights reserved.
//
#import "XDView.h"
#import "XDLayer.h"
@implementation XDView
- (instancetype)initWithFrame:(CGRect)frame
{
NSLog(@"initWithFrame:");
if (self = [super initWithFrame:frame]) {
XDLayer *layer = [[XDLayer alloc] init];
layer.bounds = CGRectMake(0, 0, 185, 185);
layer.position = CGPointMake(160, 284);
layer.backgroundColor = [UIColor lightGrayColor].CGColor;
[layer setNeedsDisplay];
[self.layer addSublayer:layer];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
NSLog(@"2-drawRect:");
//得到當(dāng)前圖形上下文是drawLayer中傳遞的
NSLog(@"CGContext:%@",UIGraphicsGetCurrentContext());
[super drawRect:rect];
}
/*UIView在顯示時(shí)其根圖層會(huì)自動(dòng)創(chuàng)建一個(gè)CGContextRef(CALayer本質(zhì)使用的是位圖上下文)
同時(shí)調(diào)用圖層代理(UIView創(chuàng)建圖層會(huì)自動(dòng)設(shè)置圖層代理為其自身)的draw: inContext:方法
并將圖形上下文作為參數(shù)傳遞給這個(gè)方法擎厢。
UIView自動(dòng)就是根圖層的代理*/
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
NSLog(@"1-drawLayer:inContext:");
NSLog(@"CGContext:%@",ctx);
[super drawLayer:layer inContext:ctx];
/*UIView會(huì)在這個(gè)方法中調(diào)用其drawRect:方法*/
}
@end
//
// SecondViewController.m
// CartoonLearn
//
// Created by xiaodoubaba on 16/2/2.
// Copyright ? 2016年 xiaodoubaba. All rights reserved.
//
#import "SecondViewController.h"
#import "XDView.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
XDView *view=[[XDView alloc]initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor=[UIColor whiteColor];
[self.view addSubview:view];
}
@end
自定義圖層繪圖.png