iOS學習——核心動畫之Layer基礎 1、CALayer是什麼? CALayer我們又稱它叫做層。在每個UIView內部都有一個layer這樣一個屬性,UIView之所以能夠顯示,就是因為它裡面有這個layer才具有顯示的功能。我們可以通過操作CALayer對象,可以很方便地調整UIView的一些 ...
iOS學習——核心動畫之Layer基礎
1、CALayer是什麼?
CALayer我們又稱它叫做層。在每個UIView內部都有一個layer這樣一個屬性,UIView之所以能夠顯示,就是因為它裡面有這個layer才具有顯示的功能。我們可以通過操作CALayer對象,可以很方便地調整UIView的一些外觀屬性,可以給UIView設置陰影,圓角,邊框等等...
2、如何操作layer改變UIView外觀?
2.1 設置陰影
//預設圖層是有陰影的, 只不過,是透明的 _RedView.layer.shadowOpacity = 1; //設置陰影的圓角 _RedView.layer.shadowRadius =10; //設置陰影的顏色,把UIKit轉換成CoreGraphics框架,用.CG開頭 _RedView.layer.shadowColor = [UIColor blueColor].CGColor;
2.2.設置邊框
//設置圖層邊框,在圖層中使用CoreGraphics的CGColorRef _RedView.layer.borderColor = [UIColor whiteColor].CGColor; _RedView.layer.borderWidth = 2;
2.3.設置圓角
//圖層的圓角半徑,圓角半徑為寬度的一半, 就是一個圓 _RedView.layer.cornerRadius = 50;
3、如何操作layer改變UIImageView的外觀?
//設置圖形邊框 _imageView.layer.borderWidth = 2; _imageView.layer.borderColor = [UIColor whiteColor].CGColor; //設置圖片的圓角半徑,必須要進行第二步的裁剪,超出裁剪區域的部分全部裁剪掉 _imageView.layer.cornerRadius = 50; _imageView.layer.masksToBounds = YES;
註意:設置圖片的圓角時,除了設置圓角半徑,還必須要進行第二步的裁剪,設置masksToBounds為yes。這是因為UIImageView當中Image並不是直接添加在層上面的,這是添加在layer當中的contents里。UIImageView中是UIView的主layer上添加了一個次layer(用來繪製contents),我們設置邊框的是主layer,但是次layer在上變,不會有任何的影響,所以當我們調用切割語句的時候,超出邊框意外的都被切割了!!
我們設置層的所有屬性它只作用在層上面,對contents裡面的東西並不起作用,所以如果我們不進行裁剪,我們是看不到圖片的圓角效果的。想要讓圖片有圓角的效果,就必須把masksToBounds這個屬性設為YES,當設為YES,把就會把超過根層以外的東西都給裁剪掉。
4、layer的 CATransform3D屬性變換
UIView和Layer都有transform屬性,但是他們的所屬有區別,類型也有區別
1.picView.transform是二維的屬性,是CGAffineTransform類型
2.picView.layer.transform是layer級別的三維屬性,是CATransform3D類型的,當然也可以做二維的事情,只有旋轉的時候才可以看出3D的效果.
//旋轉 x,y,z 分別代表x,y,z軸. CATransform3DMakeRotation(M_PI, 1, 0, 0); //平移 CATransform3DMakeTranslation(x,y,z) //縮放 CATransform3DMakeScale(x,y,z);
屬性設置有三種方法
//1.直接使用基本的三維賦值方法 picView.layer.transform = CATransform3DMakeScale(1, 2.5, 0); //2.使用KVC將CATransform3DMakeScale生成的對象給layer NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)]; [picView.layer setValue:value forKeyPath:@"transform.scale"]; //3.使用快捷方法設置屬性 [picView.layer setValue:@5 forKeyPath: "transform.scale.y"];
什麼時候用KVC?
當需要做一些快速縮放,平移,二維的旋轉時用KVC。後面forKeyPath屬性值不是亂寫的,蘋果文檔當中給了相關的屬性.
比如: [_imageView.layer setValue:@0.5 forKeyPath:@"transform.scale"];
5、如何自定義Layer ?
自定義CALayer的方式創建UIView的方式非常相似。
//創建 CALayer *layer = [CALayer layer]; //設置尺寸和位置 layer.frame = CGRectMake(50, 50, 100, 100); //設置背景 layer.backgroundColor = [UIColor redColor].CGColor; //給layer設置圖片. layer.contents = (id)[UIImage imageNamed:@"image001"].CGImage; //載入繪製 [self.view.layer addSublayer:layer];
6、為什麼要使用CGImageRef、CGColorRef?
為了保證可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
7、UIView和CALayer都能夠顯示東西,該怎樣選擇?
在明白要怎麼選擇之前,我們先瞭解一下UIView和layer的不同點:
-
- 在iOS中看的見,摸得著的都是UIView,例如一個按鈕,UITextField,UILable等等,都是UIView
- UIView之所以能夠顯示在屏幕上,是試音UIView中有一個圖層
- 在創建UIView的時候,系統會自動創建一個CALayer在其中,用於顯示東西,可以通過view.layer來去獲取圖層屬性
- 當UIView要去顯示的時候,先去調用
drawRect
方法,將要繪製的東西繪製到圖層上,然後拷貝圖層,完成了UIView的顯示 - UIView只有交互的功能,沒有顯示的功能
- CALayer只要顯示的功能,沒有交互的功能
- UIView可以做一些簡單的動畫,例如:平移,拉伸,旋轉
- 一些比較高端的動畫,都是直接操作CALayer的,可以製作3D動畫
- 使用CALayer,可以直接操作顯示的東西,例如陰影,圓角,邊框等
所以,對比CALayer,UIView多了一個事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以。
如果顯示出來的東西需要跟用戶進行交互的話,用UIView;
如果不需要跟用戶進行交互,用UIView或者CALayer都可以,CALayer的性能會高一些,因為它少了事件處理的功能,更加輕量級。
8、position和anchorPoint?
position和anchorPoint是CAlayer的兩個屬性,我們以前修改一個控制項的位置都是通過Frame的方式進行修改。現在CALayer則是通過position和anchorPoint屬性也能夠修改控制項的位置,
這兩個屬性是配合使用的。
position:它是用來設置當前的layer在父控制項當中的位置的,預設它的坐標原點,以父控制項的左上角為(0.0)點。
anchorPoint:錨點,就是把錨點定到position所指的位置。它是決點CALayer身上哪一個點會在position屬性所指的位置,anchorPoint它是以當前的layer左上角為原點(0.0),它的取值範圍是0~1,它的預設在中間也就是(0.5,0.5)的位置。
兩者結合使用,想要修改某個控制項的位置,我們可以設置它的position點。設置完畢後,layer身上的anchorPoint會自動定到position所在的位置。
//下麵兩行代碼就是設置views的 正中間 坐標(200,200) _views.layer.position = CGPointMake(200, 200); _views.layer.anchorPoint = CGPointMake(0.5, 0.5); //下麵兩行代碼就是設置views的 左上角 坐標(200,200) _views.layer.position = CGPointMake(200, 200); _views.layer.anchorPoint = CGPointMake(0, 0); //下麵兩行代碼就是設置views的 右下角 坐標(200,200) _views.layer.position = CGPointMake(200, 200); _views.layer.anchorPoint = CGPointMake(1, 1);
9、隱式動畫
9.1 什麼是隱式動畫?
瞭解什麼是隱式動畫,要先瞭解是什麼根層和非根層:
-
- 根層:UIView內部自動關聯著的那個layer我們稱它是根層.
- 非根層:自己手動創建的層,稱為非根層.
隱式動畫就是當對非根層的部分屬性進行修改時, 它會自動的產生一些動畫的效果,我們稱這個預設產生的動畫為隱式動畫.
9.2 如何取消隱式動畫?
首先要瞭解動畫底層是怎麼做的,動畫的底層是包裝成一個事務來進行的。
什麼是事務? 很多操作綁定在一起,當這些操作執行完畢後,才去執行下一個操作.
//開啟事務 [CATransaction begin]; //設置事務沒有動畫 [CATransaction setDisableActions:YES]; //設置動畫執行的時長 [CATransaction setAnimationDuration:2]; //提交事務 [CATransaction commit];
10、時鐘效果
10.1 搭建界面
界面上時針、分針、秒針不需要與用戶進行交互,所以都可以使用layer方式來做,具體時間可以用用一張圓形圖片來顯示,然後在這個imageView的layer中進行時針、分針和秒針的繪製。
做之前要觀察時針在做什麼效果。是根據當前的時間,繞著表盤的中心點進行旋轉.
要瞭解一個非常重要的知識點,無論是旋轉,縮放它都是繞著錨點進行的。要想讓時針、分針、稱針顯示的中間,還要繞著中心點進行旋轉,那就要設置它的position和anchorPoint兩個屬性.
//添加秒針 - (void)addSecond{ //創建秒針 CALayer *layer = [CALayer layer]; _secondL = layer; //設置寬高 layer.bounds = CGRectMake(0, 0, 1, 80); //設置錨點為秒針的 x軸中心,y軸最右端,該錨點的位置是時鐘圖片的正中心 layer.anchorPoint = CGPointMake(0.5, 1); layer.position = CGPointMake(_clockView.bounds.size.width * 0.5, _clockView.bounds.size.height * 0.5); //設置秒針的顏色 layer.backgroundColor = [UIColor redColor].CGColor; //將秒針的layer添加到時鐘圖片的layer中 [_clockView.layer addSublayer:layer]; } //時針、分針的添加方式類似,只是設置的寬高有點區別,不再貼出來
10.2 讓秒針開始旋轉.
//角度轉換成弧度 #define angle2Rad(angle) ((angle) / 180.0 * M_PI) //每一秒 秒針 旋轉6度 #define perSecondA 6 //每一分 分針 旋轉 #define perMinA 6 //每一小時 時針 旋轉30 #define perHourA 30 //第一分鐘 時針 旋轉0.5 #define perMinHour 0.5 //每一秒調用一次 - (void)timeChage{ NSCalendar *calendar = [NSCalendar currentCalendar]; //components日曆單元:年,月,日,時,分,秒 //fromDate:從哪個時間開始取 NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]]; //獲取當前時間的時 分 秒 NSInteger curSecond = cmp.second; NSInteger curMinute = cmp.minute; NSInteger curHour = cmp.hour; //秒針 旋轉多少度. 當前的秒數乘以每秒轉多少度. CGFloat angle = curSecond * perSecondA; self.secondL.transform = CATransform3DMakeRotation(angle2Rad(angle), 0, 0, 1); //分針 旋轉多少度. 當前的分鐘乘以每分轉多少度. CGFloat minuteA = curMinute * perMinA; self.minuteL.transform = CATransform3DMakeRotation(angle2Rad(minuteA), 0, 0, 1); //時針旋轉的度數應該是 多少小時對應的度數+分鐘對應的時針旋轉的度數 CGFloat hourA = curHour * perHourA + curMinute * perMinHour; self.hourL.transform = CATransform3DMakeRotation(angle2Rad(hourA), 0, 0, 1); }
10.3 將佈局和旋轉進行組合
每過一秒,我們的秒針就需要變化位置,所以我們我們需要設置一個定時器,在開始時每秒執行一次旋轉佈局繪製。
- (void)viewDidLoad { [super viewDidLoad]; //添加時針 分針 秒針 [self addHour]; [self addMinue]; [self addSecond]; //添加定時器,每秒進行繪製 [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChage) userInfo:nil repeats:YES]; //繪製 [self timeChage]; }