一:隱式動畫oop
#import "ViewController.h" @interface ViewController () /** <#註釋#> */ @property (nonatomic, weak) CALayer *layer; @property (weak, nonatomic) IBOutlet UIView *redView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; CALayer *layer = [CALayer layer]; layer.backgroundColor = [UIColor redColor].CGColor; layer.frame = CGRectMake(50, 50, 100, 100); self.layer = layer; [self.view.layer addSublayer:layer]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //只有非根層纔有隱式動畫,(本身手動建立的圖片) [CATransaction begin]; [CATransaction setDisableActions:NO];//此屬性可設置關掉隱士動畫 [CATransaction setAnimationDuration:5]; self.layer.backgroundColor = [UIColor greenColor].CGColor; [CATransaction commit]; self.layer.bounds = CGRectMake(0, 0, 90, 90); self.layer.backgroundColor = [UIColor greenColor].CGColor; self.layer.position = CGPointMake(100, 400); self.redView.layer.position = CGPointMake(300, 400); self.redView.layer.bounds = CGRectMake(0, 0, 100, 100); self.redView.layer.backgroundColor = [UIColor greenColor].CGColor; } @end
什麼是隱式動畫?動畫
瞭解什麼是隱式動畫前,要先了解是什麼根層和非根層.atom
根層:UIView內部自動關聯着的那個layer咱們稱它是根層.spa
非根層:本身手動建立的層,稱爲非根層.code
隱式動畫就是當對非根層的部分屬性進行修改時, 它會自動的產生一些動畫的效果.component
咱們稱這個默認產生的動畫爲隱式動畫.orm
如何取消隱式動畫?blog
首先要了解動畫底層是怎麼作的.動畫的底層是包裝成一個事務來進行的.事件
什麼是事務?圖片
不少操做綁定在一塊兒,當這些操做執行完畢後,纔去執行下一個操做.
開啓事務
[CATransaction begin];
設置事務沒有動畫
[CATransaction setDisableActions:YES];
設置動畫執行的時長
[CATransaction setAnimationDuration:2];
提交事務
[CATransaction commit];
二:時鐘效果:
效果如圖:
#import "ViewController.h" //每一秒旋轉的度數 #define perSecA 6 //每一分旋轉的度數 #define perMinA 6 //每一小時旋轉的度數 #define perHourA 30 //每一分,時針旋轉的度數 #define perMinHour 0.5 #define angle2Rad(angle) ((angle) / 180.0 * M_PI) @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *colockView; /** 當前的秒針 */ @property (nonatomic, weak) CALayer *secL; /** 當前的分針 */ @property (nonatomic, weak) CALayer *minL; /** 當前的針針 */ @property (nonatomic, weak) CALayer *hourL; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //添加時針 [self setHour]; //添加分針 [self setMin]; //添加秒針 [self setSec]; //添加定時器:scheduledTimerWithTimeInterval不用加到runLoop,由於已經默認添加到了runLoop [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES]; //添加的定時器不會當即執行,而是過一秒纔會執行,此時能夠調用定時器的fire方法,當即執行,也能夠手動調用定時器的方法 [self timeChange]; } //第一稱調用一次 - (void)timeChange { NSCalendar *cal = [NSCalendar currentCalendar]; //components:日曆的組件,年,月,日 ,時,分,秒. //fromDate:從什麼時間開始獲取 NSDateComponents *cmp = [cal components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]]; //獲取當前多少秒 NSInteger curSec = cmp.second + 1; //秒針開始旋轉 //計算秒針當前旋轉的角度. //angle = 當前多少秒 * 每一秒旋轉多少度. /** * CATransform3DMakeRotation:3D旋轉:1:必須是在layear層才能進行3D旋轉,用transform,旋轉的角度爲弧度制,2:#define angle2Rad(angle) ((angle) / 180.0 * M_PI) 3:分xyz軸, */ CGFloat secA = curSec * perSecA; self.secL.transform = CATransform3DMakeRotation(angle2Rad(secA), 0, 0, 1); //獲取當前多少秒 NSInteger curMin = cmp.minute; NSLog(@"%ld",curMin); //分針開始旋轉 //計算分針當前旋轉的角度. //angle = 當前多少分 * 每一分旋轉多少度. CGFloat minA = curMin * perMinA; self.minL.transform = CATransform3DMakeRotation(angle2Rad(minA), 0, 0, 1); //獲取當前是多少小時 NSInteger curHour = cmp.hour; NSLog(@"%ld",curMin); //分針開始旋轉 //計算分針當前旋轉的角度. //angle = 當前多少小時 * 每一小時旋轉多少度. CGFloat hourA = curHour * perHourA + curMin * perMinHour; self.hourL.transform = CATransform3DMakeRotation(angle2Rad(hourA), 0, 0, 1); } /** * 1:搭建時針秒針分針的UI效果:1:UIView和CALayear是同樣的效果,可是UIView比CALyear多了一個處理點擊事件,則CALyear相對於UIView來講更加輕量級,更加高效 2:非根層的layear也就是本身建立的layear都存在隱士動畫,要關閉隱式動畫,用動畫事物CATransaction去關閉: 開啓事務 [CATransaction begin]; 設置事務沒有動畫 [CATransaction setDisableActions:YES]; 設置動畫執行的時長 [CATransaction setAnimationDuration:2]; 提交事務 [CATransaction commit]; 3:不管是旋轉,縮放都是繞着錨點進行的.也就是默認狀況下是繞着中心點center進行的。因此要改變其繞着最後的節點旋轉,須要先定義好layear的position,在定義錨點,最後的效果是錨點與point點重合。position的位置爲錶盤的中心點,錨點的默認位置爲0.5 ,0.5,修改錶盤的錨點位置讓錨點與position點重合,這樣旋轉的時候就會繞着錨點旋轉。再把此layear添加到錶盤的layear上。 * * */ //添加秒針 //不管是旋轉,縮放都是繞着錨點進行的. - (void)setSec { CALayer *secL = [CALayer layer]; secL.bounds = CGRectMake(0, 0, 1, 80); secL.backgroundColor = [UIColor redColor].CGColor; secL.anchorPoint = CGPointMake(0.5, 1); secL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5); [self.colockView.layer addSublayer:secL]; self.secL = secL; } //添加分針 - (void)setMin { CALayer *minL = [CALayer layer]; minL.bounds = CGRectMake(0, 0, 3, 70); minL.backgroundColor = [UIColor blackColor].CGColor; minL.anchorPoint = CGPointMake(0.5, 1); minL.cornerRadius = 1.5; minL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5); [self.colockView.layer addSublayer:minL]; self.minL = minL; } //時針 - (void)setHour { CALayer *hourL = [CALayer layer]; hourL.bounds = CGRectMake(0, 0, 3, 50); hourL.backgroundColor = [UIColor blackColor].CGColor; hourL.anchorPoint = CGPointMake(0.5, 1); hourL.cornerRadius = 1.5; hourL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5); [self.colockView.layer addSublayer:hourL]; self.hourL = hourL; } //-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // // //全部旋轉,縮放,都是繞着錨點進行. // self.secL.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1); //} @end
1.搭建界面.
分析界面.
界面上時針,分針,秒針不須要與用戶進行交互.因此均可以使用layer方式來作.
作以前要觀察時針在作什麼效果.
是根據當前的時間,繞着錶盤的中心點進行旋轉.
要了解一個很是重要的知識點.不管是旋轉,縮放它都是繞着錨點.進行的.
要想讓時針,分針,稱針顯示的中間,還要繞着中心點進行旋轉.
那就要設置它的position和anchorPoint兩個屬性.
建立秒針
CALayer *layer = [CALayer layer];
_secLayer = layer;
layer.bounds = CGRectMake(0, 0, 1, 80);
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;
[_clockView.layer addSublayer:layer];
2.讓秒針開始旋轉.
讓秒針旋轉.因此要計算當前的旋轉度是多少?
當前的旋轉角度爲:當前的時間 * 每秒旋轉多少度.
計算每一秒旋轉多少度.
60秒轉一圈360度
360 除以60就是每一秒轉多少度.每秒轉6度.
獲取當前的時間
建立日曆類
NSCalendar *calendar = [NSCalendar currentCalendar];
把日曆類轉換成一個日期組件
日期組件(年,月,日,時,分,秒)
component:日期組件有哪些東西組成,他是一個枚舉,裏面有年月日時分秒
fromDate:當前的日期
NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond
fromDate:[NSDate date]];
咱們的秒就是保存在日期組件裏面,它裏面提供了不少get方法.
NSInteger second = cmp.second;
那麼當前秒針旋轉的角度就是
當前的秒數乘以每秒轉多少度.
second * perSecA
還得要把角度轉換成弧度.
由於下面分針,時針也得要用到, 就把它抽出一個速參數的宏.
#define angle2Rad(angle) ((angle) / 180.0 * M_PI)
讓它每隔一秒旋轉一次.因此添加一個定時器.
每一個一秒就調用,旋轉秒針
- (void)timeChange{
獲取當前的秒數
建立日曆類
NSCalendar *calendar = [NSCalendar currentCalendar];
把日曆類轉換成一個日期組件
日期組件(年,月,日,時,分,秒)
component:日期組件有哪些東西組成,他是一個枚舉,裏面有年月日時分秒
fromDate:當前的日期
NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond
fromDate:[NSDate date]];
咱們的秒就是保存在日期組件裏面,它裏面提供了不少get方法.
NSInteger second = cmp.second;
秒針旋轉多少度.
CGFloat angel = angle2Rad(second * perSecA);
旋轉秒針
self.secondL.transform = CATransform3DMakeRotation(angel, 0, 0, 1);
}
運行發現他會一下只就調到某一個時間纔開始旋轉
一開始的時候就要來到這個方法,獲取當前的秒數把它定位好.
要在添加定時器以後就調用一次timeChange方法.
3.添加分針
快速拷貝一下,而後添加一個分針成員屬性.
修改寬度,修改顏色
也得要讓它旋轉,
要算出每分鐘轉多少度
轉60分鐘恰好是一圈
因此每一分鐘也是轉6度.
獲取當前多少分?
一樣是在日期組件裏面得到
裏面有左移符號,右移符號.他就能夠用一個並運算
如今同時讓他支持秒數和分 後面直接加上一個 |
NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond |
NSCalendarUnitMinute
fromDate:[NSDate date]];
CGFloat minueteAngel = angle2Rad(minute * perMinuteA);
self.minueL.transform = CATransform3DMakeRotation(minueteAngel, 0, 0, 1);
4.添加時針
一樣複製以前的,添加一個小時屬性
小時轉多少度
當前是多少小時,再計算先每一小時轉多少度.
12個小時轉一圈. 360除以12,每小時轉30度
時針旋轉多少度
CGFloat hourAngel = angle2Rad(hour * perHourA);
旋轉時針
self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);
直接這樣寫會有問題
就是沒轉一分鐘,小時也會移動一點點
接下來要算出,每一分鐘,小時要轉多少度
60分鐘一小時.一小時轉30度.
30 除以60,就是每一分鐘,時針轉多少度.0.5
時針旋轉多少度
CGFloat hourAngel = angle2Rad(hour * perHourA + minute * perMinuteHourA);
旋轉時針
self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);