純屬原創(chuàng)绊序,轉(zhuǎn)載請標(biāo)明出處,謝謝
首先我們先看一下需求
按照MAC的系統(tǒng)時鐘仿照寫一個類似的時鐘效果
然后我們著手分析一個這個如何實現(xiàn)
首先這個不需要和用戶有任何交互缎患,所以我們推薦使用CALayer隱式動畫去完成
然后我們讓設(shè)計人員先畫出一個表盤給我們滞欠,設(shè)置他的長寬都為200
其次燥滑,我們就要通過需求來描述CALayer的anchorPoint與position點在哪里
至于這兩個點是什么(也就是“錨點”),徹底理解position與anchorPoint - yongyinmg的專欄 - 博客頻道 - CSDN.NET香罐,這篇文章說的很清楚了卧波,這里就不跟大家解釋
我們可以看到,所有的layer都是基于錨點去旋轉(zhuǎn)的庇茫,也就是表盤的中心點港粱,那么position屬性也就是表盤的長寬的一半,由于anchorPoint的X,Y屬性取值范圍是0-1之間查坪,以秒針舉例寸宏,如果我們想讓秒針站立在表盤中上,那么秒針的X即為0.5偿曙,Y為1
在設(shè)置下秒針的bound氮凝,寬度為1,長度為表盤的半徑-20
這樣我們可以輕松的將秒針針添加到表盤上
CALayer * secondL = [CALayer layer];
secondL.backgroundColor = [UIColor redColor].CGColor ;
// 設(shè)置錨點
secondL.anchorPoint = CGPointMake(0.5, 1);
secondL.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
secondL.bounds = CGRectMake(0, 0, 1, kClockW * 0.5 - 20);
[_clockView.layer addSublayer:secondL];
_secondLayer = secondL;
同理望忆,時針和分針也是一樣罩阵,只不過長度和顏色,圓角不一樣
CALayer * layer = [CALayer layer];
layer.backgroundColor = [UIColor blackColor].CGColor ;
// 設(shè)置錨點
layer.anchorPoint = CGPointMake(0.5, 1);
layer.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
layer.bounds = CGRectMake(0, 0, 4, kClockW * 0.5 - 20);
layer.cornerRadius = 4;
[_clockView.layer addSublayer:layer];
_mintueLayer = layer;
CALayer * layer = [CALayer layer];
layer.backgroundColor = [UIColor blackColor].CGColor ;
// 設(shè)置錨點
layer.anchorPoint = CGPointMake(0.5, 1);
layer.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
layer.bounds = CGRectMake(0, 0, 4, kClockW * 0.5 - 40);
layer.cornerRadius = 4;
[_clockView.layer addSublayer:layer];
_hourLayer = layer;
這里一定要注意的是添加順序启摄,一般來講秒針在最上層稿壁,所以秒針的layer是最后添加的
現(xiàn)在UI層我們已經(jīng)添加好了,接下來就該考慮如何讓時鐘動起來了
讓時鐘動起來鞋仍,我們先要知道時分秒他們在表盤上所謂轉(zhuǎn)動的角度
通過小學(xué)運算可以得知常摧,秒針在一秒鐘內(nèi)在表盤里轉(zhuǎn)動的度數(shù)是6度(一個圓形是360度,360除以60)威创,拿現(xiàn)在的系統(tǒng)的秒數(shù)*6就是現(xiàn)在秒針的具體度數(shù)
分針在一分鐘內(nèi)在表盤轉(zhuǎn)動的度數(shù)也是6度
而時針呢落午,一小時時針變化為360除以12等于30度,但是有個問題肚豺,常理知溃斋,時鐘并不是只有在分針轉(zhuǎn)到12點的時候才變化,它表盤里也會隨著分針的變化而變化(比如說1:30吸申,時針不可能只還停留在1這個位置梗劫,等到2:00的時候才突然變化)所以這個角度還需要加上分針對它的變化。這個怎么算呢截碴,拿30度除以60現(xiàn)在的系統(tǒng)分鐘數(shù)就可以得到了梳侨,也就是0.5現(xiàn)在的分鐘數(shù)就是時鐘在以分鐘作單位時轉(zhuǎn)動的度數(shù)
30*系統(tǒng)小時+0.5*系統(tǒng)分鐘
由于這些都是不可變化的,我們來抽成宏
// 1秒6度(秒針)
#define perSecondA 6
// 1分鐘6度(分針)
#define perMintueA 6
// 1小時30度(時針)
#define perHourA 30
// 每分鐘時針轉(zhuǎn)(30 / 60 °)
#define perMinHourA 0.5
有了這些角度之后日丹,剩下的就很好做了走哺,我們在viewDidLoad的里添加一個定時器
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
然后在這個timeChange方法里,設(shè)置時分秒的旋轉(zhuǎn)形變就可以了哲虾,這里注意丙躏,CATransform3DMakeRotation這個接受的弧度而不是角度,我們再抽出一個宏來將角度轉(zhuǎn)化為弧度
#define angle2radion(angle) ((angle) / 180.0 * M_PI)
- (void)timeChange{
// 獲取當(dāng)前系統(tǒng)時間
NSCalendar * calender = [NSCalendar currentCalendar];
NSDateComponents * cmp = [calender components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
CGFloat second = cmp.second;
CGFloat secondA = (second * perSecondA) ;
NSInteger minute = cmp.minute;
CGFloat mintuteA = minute * perMintueA ;
NSInteger hour = cmp.hour;
CGFloat hourA = hour * perHourA + minute * perMinHourA;
_secondLayer.transform = CATransform3DMakeRotation(angle2radion(secondA), 0, 0, 1);
_mintueLayer.transform = CATransform3DMakeRotation(angle2radion(mintuteA), 0, 0, 1);
_hourLayer.transform = CATransform3DMakeRotation(angle2radion(hourA), 0, 0, 1);
}
做到這里束凑,基本上已經(jīng)大功告成晒旅,讓我們運行一下
時鐘已經(jīng)隨著系統(tǒng)時間轉(zhuǎn)了起來,還可以在修改一些別的樣式汪诉,到時候就看開發(fā)者如何發(fā)揮了
本Dome的Github地址
https://github.com/DriverWang/YCClock