[注意]轉載時請注明出處博客園-吃唐僧肉的小悟空http://www.49028c.com/hukezhu/
今天使用CALayer的"定位點(錨點)"實現了一個時鐘動畫,其實就是一個小的時鐘,只是實現了功能,沒有做出絢麗的效果.使用UIView實現的,其實只是單純的使用layer也可以實現.主要用到了 Quartz2D畫圖/ 事件處理/核心動畫方面的知識.
代碼不是很多,直接附上源碼,注釋比較詳細,在源碼后面再進行解釋其中的一些知識點和注意點.
下圖為應用截圖,使用gif,沒有制作好,見諒哈.[此處圖片有一點小問題,時間顯示正常,指針處有點問題,代碼中修改過來了]
下圖為模擬器與電腦時間對比圖,和正常時間一樣.
下面附上源代碼:
viewController.m
這個是最初的源碼,界面上沒有顯示數字時間的功能,把能夠顯示數字時間的源碼放到最后面
1 // 2 // ViewController.m 3 // 01-時鐘動畫time 4 // 5 // Created by hukezhu on 15/6/12. 6 // Copyright (c) 2015年 hukezhu. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController () 12 //秒針view 13 @PRoperty(nonatomic,strong)UIView *secondView; 14 //分針view 15 @property(nonatomic,strong)UIView *minView; 16 //時針view 17 @property(nonatomic,strong)UIView *hourView; 18 @end 19 20 @implementation ViewController 21 22 - (void)viewDidLoad { 23 [super viewDidLoad]; 24 //設置背景顏色 25 self.view.backgroundColor = [UIColor greenColor]; 26 27 //創建一個表盤view 28 UIView *clockView = [[UIView alloc]init]; 29 //設置位置 30 clockView.center = self.view.center; 31 //設置大小 32 clockView.layer.bounds = CGRectMake(0, 0, 214, 214); 33 34 //設置顯示內容 35 clockView.layer.contents = (__bridge id)([UIImage imageNamed:@"clock1"].CGImage); 36 //設置圓角半徑 37 clockView.layer.cornerRadius = 107; 38 //設置裁剪 39 clockView.layer.masksToBounds = YES; 40 //將clockView添加到控制器view中 41 [self.view addSubview:clockView]; 42 43 44 45 46 //創建一個秒針view 47 UIView *secondView = [[UIView alloc]init]; 48 secondView.center = clockView.center; 49 secondView.layer.bounds = CGRectMake(0, 0, 2, 90); 50 secondView.layer.backgroundColor = [UIColor redColor].CGColor; 51 secondView.layer.anchorPoint = CGPointMake(0.5, 1); 52 53 self.secondView = secondView; 54 [self.view addSubview:secondView]; 55 56 57 58 //創建一個分針view 59 UIView *minView = [[UIView alloc]init]; 60 minView.center = clockView.center; 61 minView.layer.bounds = CGRectMake(0, 0, 4, 70); 62 minView.layer.backgroundColor = [UIColor blueColor].CGColor; 63 minView.layer.anchorPoint = CGPointMake(0.5, 1); 64 65 self.minView = minView; 66 [self.view addSubview:minView]; 67 68 69 70 //創建一個時針view 71 UIView *hourView = [[UIView alloc]init]; 72 hourView.center = clockView.center; 73 hourView.layer.bounds = CGRectMake(0, 0, 6, 50); 74 hourView.layer.backgroundColor = [UIColor blackColor].CGColor; 75 hourView.layer.anchorPoint = CGPointMake(0.5, 1); 76 77 self.hourView = hourView; 78 [self.view addSubview:hourView]; 79 80 81 // 開啟一個計時器控件 82 //NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(move) userInfo:nil repeats:YES]; 83 //創建一個對象 84 CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(move)]; 85 //啟動這個link 86 [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 87 } 88 89 90 - (void)move{ 91 92 93 //1.計算對應的弧度 94 CGFloat angle = M_PI * 2 / 60.0; 95 CGFloat angleMin = M_PI * 2 / 60.0; 96 CGFloat angleHour = M_PI * 2 / 12.0 ; 97 98 //2.獲取當前事件 99 NSDate *date = [NSDate date];100 101 //創建一個日歷牌對象(NSCalender),通過這個對象才能獲取NSDate中的日期時間的每一部分102 NSCalendar *calender = [NSCalendar currentCalendar];103 104 //告訴日歷牌對象,需要獲取哪些部分的值105 106 //取得當前的秒107 NSInteger secs = [calender component:NSCalendarUnitSecond fromDate:date];108 //取得當前的分109 NSInteger mins = [calender component:NSCalendarUnitMinute fromDate:date];110 //取得當前的時111 NSInteger hours = [calender component:NSCalendarUnitHour fromDate:date];112 113 114 //NSLog(@"%zd,%zd,%zd",hours,mins,secs);//測試用115 116 117 //計算本次旋轉應該旋轉到的弧度數118 angle = secs *angle;119 angleMin = mins *angleMin + angle/60.0;120 angleHour = hours *angleHour + angleMin/12.0 ;121 122 //讓時分秒針旋轉123 self.secondView.transform = CGAffineTransformMakeRotation(angle);124 self.minView.transform = CGAffineTransformMakeRotation(angleMin);125 self.hourView.transform = CGAffineTransformMakeRotation(angleHour);126 127 }128 129 @end
當然,這里面的表盤使用的時圖片,我們也可以自己畫出來,但是此處有圖片資源,就直接使用了.(注意需要剪切圖片為圓形,當然,有方形的表盤,但是此處是圓形表盤,所以將圖片切割成圓形).
注意:可以使用NSTimer創建一個定時器,但是通過 NSTimer 實現的動畫可能造成卡頓、不連貫的情況(NSTimer 不準確),此處使用CADisplayLink.
主要思路就是:
獲取當前系統中的時間的某一部分的方法
1 //2.獲取當前事件 2 NSDate *date = [NSDate date]; 3 4 //創建一個日歷牌對象(NSCalender),通過這個對象才能獲取NSDate中的日期時間的每一部分 5 NSCalendar *calender = [NSCalendar currentCalendar]; 6 7 //告訴日歷牌對象,需要獲取哪些部分的值 8 9 //取得當前的秒10 NSInteger secs = [calender component:NSCalendarUnitSecond fromDate:date];11 //取得當前的分12 NSInteger mins = [calender component:NSCalendarUnitMinute fromDate:date];13 //取得當前的時14 NSInteger hours = [calender component:NSCalendarUnitHour fromDate:date];15 16 17 //NSLog(@"%zd,%zd,%zd",hours,mins,secs);//測試用
知識點:
注意: 在使用 Quartz2D 繪圖的時候, 對繪圖上下文的旋轉是對坐標系的旋轉, 通過 UI 控件的 transform 對控件做旋轉是按照 Center 來旋轉的。
注意: 控件的 center 屬性, 其實就是對應的 CALayer的 postion。所以控件的 center并不是永遠表示控件的中心點。
//寬度和高度@property CGRect bounds;//位置(默認指中點,具體由anchorPoint決定)@property CGPoint position;//錨點(x,y的范圍都是0-1),決定了position的含義@property CGPoint anchorPoint;//背景顏色(CGColorRef類型)@property CGColorRef backgroundColor;//形變屬性@property CATransform3D transform;//邊框顏色(CGColorRef類型)@property CGColorRef borderColor;//邊框寬度@property CGFloat borderWidth;//圓角半徑@property CGFloat cornerRadius;//內容(比如設置為圖片CGImageRef)@property(retain) id contents;
UIView和CALayer的使用區別:
UIView : 接受和處理系統事件、觸摸事件。
界面上有顯示時間的label:(主要是一個定時器的功能,1秒刷新一次,顯示在label上,實時動態的更新時間)
源碼代碼:
1 // 2 // ViewController.m 3 // 01-時鐘動畫time 4 // 5 // Created by hukezhu on 15/6/12. 6 // Copyright (c) 2015年 hukezhu. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController () 12 //秒針view 13 @property(nonatomic,strong)UIView *secondView; 14 //分針view 15 @property(nonatomic,strong)UIView *minView; 16 //時針view 17 @property(nonatomic,strong)UIView *hourView; 18 //定時器 19 @property(nonatomic,strong)NSTimer *timer; 20 //顯示時間的label 21 @property(nonatomic,strong)UILabel *timeLabel; 22 @end 23 24 @implementation ViewController 25 26 - (void)viewDidLoad { 27 [super viewDidLoad]; 28 //設置背景顏色 29 self.view.backgroundColor = [UIColor greenColor]; 30 31 //創建一個表盤view 32 UIView *clockView = [[UIView alloc]init]; 33 //設置位置 34 clockView.center = self.view.center; 35 //設置大小 36 clockView.layer.bounds = CGRectMake(0, 0, 214, 214); 37 38 //設置顯示內容 39 clockView.layer.contents = (__bridge id)([UIImage imageNamed:@"clock1"].CGImage); 40 //設置圓角半徑 41 clockView.layer.cornerRadius = 107; 42 //設置裁剪 43 clockView.layer.masksToBounds = YES; 44 //將clockView添加到控制器view中 45 [self.view addSubview:clockView]; 46 47 48 //創建一個顯示時間的label 49 UILabel *label = [[UILabel alloc]init]; 50 51 //設置位置 52 label.center = CGPointMake(clockView.center.x, clockView.center.y + 130); 53 //設置大小(這樣設置不合理,代碼很爛,只是單純的為了實現這個小功能,也沒有做自動布局) 54 label.frame = CGRectMake(clockView.center.x-60, clockView.center.y + 150, 100, 44); 55 //設置背景顏色 56 label.backgroundColor = [UIColor whiteColor]; 57 //設置字體顏色 58 label.textColor = [UIColor redColor]; 59 //設置字體居中 60 label.textAlignment = NSTextAlignmentCenter; 61 //設置字體大小 62 label.font = [UIFont systemFontOfSize:20]; 63 64 self.timeLabel = label; 65 [self.view addSubview:label]; 66 67 68 69 70 71 //創建一個秒針view 72 UIView *secondView = [[UIView alloc]init]; 73 secondView.center = clockView.center; 74 secondView.layer.bounds = CGRectMake(0, 0, 2, 90); 75 secondView.layer.backgroundColor = [UIColor redColor].CGColor; 76 secondView.layer.anchorPoint = CGPointMake(0.5, 1); 77 78 self.secondView = secondView; 79 [self.view addSubview:secondView]; 80 81 82 83 //創建一個分針view 84 UIView *minView = [[UIView alloc]init]; 85 minView.center = clockView.center; 86 minView.layer.bounds = CGRectMake(0, 0, 4, 70); 87 minView.layer.backgroundColor = [UIColor blueColor].CGColor; 88 minView.layer.anchorPoint = CGPointMake(0.5, 1); 89 90 self.minView = minView; 91 [self.view addSubview:minView]; 92 93 94 95 //創建一個時針view 96 UIView *hourView = [[UIView alloc]init]; 97 hourView.center = clockView.center; 98 hourView.layer.bounds = CGRectMake(0, 0, 6, 50); 99 hourView.layer.backgroundColor = [UIColor blackColor].CGColor;100 hourView.layer.anchorPoint = CGPointMake(0.5, 1);101 102 self.hourView = hourView;103 [self.view addSubview:hourView];104 105 106 // 開啟一個計時器控件107 //NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(move) userInfo:nil repeats:YES];108 //創建一個對象109 CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(move)];110 //啟動這個link111 [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];112 113 114 _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timeRun) userInfo:nil repeats:YES];115 }116 117 - (void)timeRun{118 119 NSDateFormatter *fmt = [[NSDateFormatter alloc] init];120 121 [fmt setDateFormat:@" HH:mm:ss"];122 123 NSString *time = [fmt stringFromDate:[NSDate date]];124 125 [self.timeLabel setText:time];126 127 128 129 }130 131 132 133 - (void)move{134 135 136 //1.計算對應的弧度137 CGFloat angle = M_PI * 2 / 60.0;138 CGFloat angleMin = M_PI * 2 / 60.0;139 CGFloat angleHour = M_PI * 2 / 12.0 ;140 141 //2.獲取當前事件142 NSDate *date = [NSDate date];143 144 //創建一個日歷牌對象(NSCalender),通過這個對象才能獲取NSDate中的日期時間的每一部分145 NSCalendar *calender = [NSCalendar currentCalendar];146 147 //告訴日歷牌對象,需要獲取哪些部分的值148 149 //取得當前的秒150 NSInteger secs = [calender component:NSCalendarUnitSecond fromDate:date];151 //取得當前的分152 NSInteger mins = [calender component:NSCalendarUnitMinute fromDate:date];153 //取得當前的時154 NSInteger hours = [calender component:NSCalendarUnitHour fromDate:date];155 156 157 //NSLog(@"%zd,%zd,%zd",hours,mins,secs);//測試用158 159 160 //計算本次旋轉應該旋轉到的弧度數161 angle = secs *angle;162 angleMin = mins *angleMin + angle/60.0;163 angleHour = hours *angleHour + angleMin/12.0 ;164 165 //讓時分秒針旋轉166 self.secondView.transform = CGAffineTransformMakeRotation(angle);167 self.minView.transform = CGAffineTransformMakeRotation(angleMin);168 self.hourView.transform = CGAffineTransformMakeRotation(angleHour);169 170 }171 172 @end
這段代碼不是很規范,有許多需要優化的地方,只是單純的實現了這個功能,請勿噴~~~~~~~~
新聞熱點
疑難解答