CALayer
- 父類是NSObject
- layer(圖層):在iOS中屠橄,UIView之所以能顯示在屏幕上梁厉,完全是因?yàn)樗鼉?nèi)部的一個(gè)圖層咬荷,它本身不具備顯示的功能,這個(gè)圖層(即CALayer對象)听隐,可以通過layer屬性可以訪問這個(gè)層
@property(nonatomic,readonly,retain) CALayer *layer;
- 創(chuàng)建時(shí)間:創(chuàng)建UIView時(shí)就生成成員屬性layer
- 顯示時(shí)間:當(dāng)UIView需要顯示到屏幕上時(shí),會調(diào)用drawRect:方法進(jìn)行繪圖哄啄,并且會將所有內(nèi)容繪制在自己的圖層上雅任,繪圖完畢后,系統(tǒng)會將圖層拷貝到屏幕上咨跌,于是就完成了UIView的顯示
- 通過操作CALayer對象沪么,可以很方便地調(diào)整UIView的一些外觀屬性
- 陰影
- 圓角大小
- 邊框?qū)挾群皖伾?/li>
- 給圖層添加動畫,來實(shí)現(xiàn)一些比較炫酷的效果等
CALayer常見屬性
寬度和高度
@property CGRect bounds;
位置(默認(rèn)指中點(diǎn)锌半,具體由anchorPoint決定)
@property CGPoint position;
錨點(diǎn)(x,y的范圍都是0-1)禽车,決定了position的含義
@property CGPoint anchorPoint;
背景顏色(CGColorRef類型)
@property CGColorRef backgroundColor;
形變屬性
類型:CATransform3DMakeScale、CATransform3DMakeRotation等
@property CATransform3D transform;
邊框顏色(CGColorRef類型)
@property CGColorRef borderColor;
邊框?qū)挾?@property CGFloat borderWidth;
//圓角半徑
@property CGColorRef borderColor;
內(nèi)容(比如設(shè)置為圖片CGImageRef)
@property(retain) id contents;
// 超出主層邊框的都會被裁減調(diào)用
@property BOOL masksToBounds
_imageView.layer.masksToBounds = YES;
關(guān)于CALayer的疑惑
- 首先CALayer是定義在QuartzCore框架中的刊殉,CGImageRef殉摔、CGColorRef兩種數(shù)據(jù)類型是定義在CoreGraphics框架中的,UIColor记焊、UIImage是定義在UIKit框架中的
其次QuartzCore框架和CoreGraphics框架是可以跨平臺使用的逸月,在iOS和Mac OS X上都能使用但是UIKit只能在iOS中使用
為了保證可移植性,QuartzCore不能使用UIImage遍膜、UIColor碗硬,只能使用CGImageRef、CGColorRef
UIView和CALayer的選擇
- 如果顯示出來的東西需要跟用戶進(jìn)行交互的話瓢颅,用UIView恩尾;
- 如果不需要跟用戶進(jìn)行交互,用UIView或者CALayer都可以
- CALayer的性能會高一些惜索,因?yàn)樗倭耸录幚淼墓δ芴厮瘢虞p量級
position和anchorPoint
- CALayer有2個(gè)非常重要的屬性:position和anchorPoint
-
position:
- 用來設(shè)置CALayer在父層中的位置
- 以父層的左上角為原點(diǎn)(0, 0)
@property CGPoint position;
-
anchorPoint(定位點(diǎn),錨點(diǎn)):
- 決定著CALayer身上的哪個(gè)點(diǎn)會在position屬性所指的位置
- 以自己的左上角為原點(diǎn)(0, 0)
- 它的x巾兆、y取值范圍都是0~1猎物,默認(rèn)值為(0.5, 0.5),是比例值角塑。
- 如默認(rèn)值(0.5, 0.5)蔫磨,即layer的中心點(diǎn)在positon位置上;若是(1圃伶,1)堤如,則是layer的右下角的點(diǎn)在position的位置上蒲列,對平常的UIView來說,錨點(diǎn)相當(dāng)于(0搀罢,0)
@property CGPoint anchorPoint;
隱式動畫
-
隱式動畫:當(dāng)對非Root Layer的部分屬性進(jìn)行修改時(shí)蝗岖,默認(rèn)會自動產(chǎn)生一些動畫效果,而這些屬性稱為Animatable Properties(可動畫屬性)
- 根層:每一個(gè)UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個(gè)CALayer,我們可用稱這個(gè)Layer為Root Layer(根層)
- 非根層:所有的非Root Layer榔至,也就是手動創(chuàng)建的CALayer對象抵赢,都存在著隱式動畫
-
幾個(gè)常見的Animatable Properties:
- bounds:用于設(shè)置CALayer的寬度和高度。修改這個(gè)屬性會產(chǎn)生縮放動畫
- backgroundColor:用于設(shè)置CALayer的背景色唧取。修改這個(gè)屬性會產(chǎn)生背景色的漸變動畫
- position:用于設(shè)置CALayer的位置铅鲤。修改這個(gè)屬性會產(chǎn)生平移動畫
可以通過動畫事務(wù)(CATransaction)關(guān)閉默認(rèn)的隱式動畫效果
// 開啟事務(wù)
[CATransaction begin];
// 設(shè)置動畫時(shí)長
[CATransaction setAnimationDuration:0.5];
// 動畫
// 可動畫屬性
_layer.position = CGPointMake(arc4random_uniform(250), arc4random_uniform(500));
// 背景顏色
_layer.backgroundColor = [self randomColor].CGColor;
// 圓角半徑
// 長方形的時(shí)候不能設(shè)置圓角變成圓
// 做動畫,盡量不要使用修改圓角半徑做動畫
_layer.cornerRadius = arc4random_uniform(50);
// 陰影(陰影設(shè)置的效果是太陽效果)
// 顯示陰影
_redView.layer.shadowOpacity = 1;
// _redView.layer.shadowOffset = CGSizeMake(10, 10);
_redView.layer.shadowColor = [UIColor yellowColor].CGColor;
_redView.layer.shadowRadius = 10;
// 邊框
_layer.borderWidth = arc4random_uniform(10);
_layer.borderColor = [self randomColor].CGColor;
// 提交事務(wù)
[CATransaction commit];
CALayer常用方法
[self.view.layer addSublayer:layer];
特殊的View
- UIImgeView + UIImageView圓角半徑 + 主層和contents + 裁剪 + 陰影無效,達(dá)到效果枫弟,圓形頭像
- 默認(rèn)UIImageView的圖片不是顯示到主層的子層中,而是在content層中
時(shí)鐘實(shí)現(xiàn)案例
- 實(shí)現(xiàn)步驟:
- 布局控件:指針都是繞圓心旋轉(zhuǎn)邢享,所以要設(shè)置錨點(diǎn)和positon在圓心
- 開啟計(jì)時(shí),調(diào)用時(shí)間改變方法
- 生成日歷對象淡诗,獲取當(dāng)前時(shí)間
- 計(jì)算時(shí)分秒轉(zhuǎn)動角度骇塘,設(shè)置形變旋轉(zhuǎn)
- 初始化時(shí)針,分針袜漩,秒針位置
// 每秒秒針轉(zhuǎn)6°
#define kPerSecondA 6
// 每分鐘分針轉(zhuǎn)6°
#define kPerMinuteA 6
// 每小時(shí)時(shí)針轉(zhuǎn)30°
#define kPerHourA 30
// 每分鐘時(shí)針轉(zhuǎn)0.5°
#define kPerMinHourA 0.5
// 每秒分針轉(zhuǎn)0.1°
#define kPerMinSecA 0.1
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) CALayer *secLayer;
@property (weak, nonatomic) CALayer *minLayer;
@property (weak, nonatomic) CALayer *hourLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 小時(shí)
[self setUpHourLayer];
// 分
[self setUpMinLayer];
// 秒
[self setUpSecLayer];
// 定時(shí)器
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
// 初始化始終
[self timeChange];
}
- (void)timeChange
{
##核心代碼
// 獲取當(dāng)前是多少秒
// 獲取當(dāng)前的日歷對象
NSCalendar *calendar = [NSCalendar currentCalendar];
// 日期組件:秒,分,小時(shí),年,月,日......
// NSCalendarUnit:表示日期組件有哪些組成
NSDateComponents *dataCmp = [calendar components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
// 獲取分
NSInteger minute = dataCmp.minute;
##
// 計(jì)算下分針轉(zhuǎn)多少度
CGFloat minA = (min * kPerMinuteA + sec * kPerMinSecA) / 180.0 * M_PI;
// 旋轉(zhuǎn)分針
_minLayer.transform = CATransform3DMakeRotation(minA, 0, 0, 1);
// 獲取小時(shí)
NSInteger hour = dataCmp.hour;
// 計(jì)算時(shí)針轉(zhuǎn)多少度 = 當(dāng)前有多少小時(shí) * 每小時(shí)轉(zhuǎn)的度數(shù)30° + 當(dāng)前多少分鐘 * 每分鐘時(shí)針轉(zhuǎn)多少0.5
CGFloat hourA = (hour * kPerHourA + minute * kPerMinHourA) / 180.0 * M_PI;
// 旋轉(zhuǎn)時(shí)針
_hourLayer.transform = CATransform3DMakeRotation(hourA, 0, 0, 1);
// 獲取秒數(shù)
NSInteger sec = dataCmp.second;
// 秒針轉(zhuǎn)多少度
CGFloat secA = (sec * kPerSecondA) / 180.0 * M_PI;
// 旋轉(zhuǎn)秒針
_secLayer.transform = CATransform3DMakeRotation(secA, 0, 0, 1);
}
// 秒
- (void)setUpSecLayer
{
CALayer *layer = [CALayer layer];
_secLayer = layer;
layer.backgroundColor = [UIColor redColor].CGColor;
// 繞著錨點(diǎn)旋轉(zhuǎn),設(shè)置錨點(diǎn)
layer.anchorPoint = CGPointMake(0.5, 1);
layer.position = CGPointMake(_imageView.bounds.size.width * 0.5, _imageView.bounds.size.height * 0.5);
layer.bounds = CGRectMake(0, 0, 1, 80);
[_imageView.layer addSublayer:layer];
}
// 分
- (void)setUpMinLayer
{
CALayer *layer = [CALayer layer];
_minLayer = layer;
layer.cornerRadius = 4;
layer.backgroundColor = [UIColor blackColor].CGColor;
// 繞著錨點(diǎn)旋轉(zhuǎn),設(shè)置錨點(diǎn)
layer.anchorPoint = CGPointMake(0.5, 1);
layer.position = CGPointMake(_imageView.bounds.size.width * 0.5, _imageView.bounds.size.height * 0.5);
layer.bounds = CGRectMake(0, 0, 4, 80);
[_imageView.layer addSublayer:layer];
}
// 小時(shí)
- (void)setUpHourLayer
{
CALayer *layer = [CALayer layer];
_hourLayer = layer;
layer.cornerRadius = 4;
layer.backgroundColor = [UIColor blackColor].CGColor;
// 繞著錨點(diǎn)旋轉(zhuǎn),設(shè)置錨點(diǎn)
layer.anchorPoint = CGPointMake(0.5, 1);
layer.position = CGPointMake(_imageView.bounds.size.width * 0.5, _imageView.bounds.size.height * 0.5);
layer.bounds = CGRectMake(0, 0, 4, 75);
[_imageView.layer addSublayer:layer];
}