本篇介绍下iOS中钟表中时分秒针的实现:
先看下最终效果:
几个前提知识点:
时分秒针的长度都是以钟表的半径为基本调整的;
钟表转动时改变的弧度;
每秒钟秒针转6°,每分钟分针转6°,每小时时针转30°,每分钟时针转0.5°。
为此定义几个宏:
/** 钟表背景的半径 */
#define KClockRadius CGRectGetWidth(self.clockImageView.frame) * 0.5
/** 角度转弧度 */
#define KAngle2Radian(angle) ((angle) / 180.0 * M_PI)
/** 每秒钟秒针转多少角度 360.0 / 60 */
#define KPerSecondA 6
/** 每分钟分针转多少角度 360.0 / 60 */
#define KPerMinuteA 6
/** 每小时时针转多少角度 360.0 / 12 */
#define KPerHourA 30
/** 每分钟时针转多少角度 360.0 / 12 / 60 */
#define KPerMinuteHourLA 0.5
思路:
我们看到的钟表是一个UIImageView,时分秒针是是三个CALayer,下面显示的时间就是一个简单的UILabel。先拖一个UIImageView和一个UILabel到xib或SB上,并拖线到.m文件。并定义三个CALayer属性。代码如下:
@interface ViewController ()
/** 当前时间label */
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
/** 钟表背景图 */
@property (weak, nonatomic) IBOutlet UIImageView *clockImageView;
/** 秒针layer */
@property (nonatomic, strong) CALayer *secondLayer;
/** 分针layer */
@property (nonatomic, strong) CALayer *minuteLayer;
/** 时针layer */
@property (nonatomic, strong) CALayer *hourLayer;
@end
懒加载三个layer:
设置其位置、锚点、颜色、宽高、圆角半径等属性。
#pragma mark - lazy loading
- (CALayer *)secondLayer {
if (!_secondLayer) {
_secondLayer = [[CALayer alloc] init];
_secondLayer.backgroundColor = [UIColor redColor].CGColor;
_secondLayer.anchorPoint = CGPointMake(0.5, 0.9);
_secondLayer.position = CGPointMake(KClockRadius, KClockRadius);
_secondLayer.bounds = CGRectMake(0, 0, 1, KClockRadius-10);
}
return _secondLayer;
}
- (CALayer *)minuteLayer {
if (!_minuteLayer) {
_minuteLayer = [[CALayer alloc] init];
_minuteLayer.backgroundColor = [UIColor blackColor].CGColor;
_minuteLayer.anchorPoint = CGPointMake(0.5, 1);
_minuteLayer.position = CGPointMake(KClockRadius, KClockRadius);
_minuteLayer.bounds = CGRectMake(0, 0, 2, KClockRadius-20);
_minuteLayer.cornerRadius = 2;
}
return _minuteLayer;
}
- (CALayer *)hourLayer {
if (!_hourLayer) {
_hourLayer = [[CALayer alloc] init];
_hourLayer.backgroundColor = [UIColor blackColor].CGColor;
_hourLayer.anchorPoint = CGPointMake(0.5, 1);
_hourLayer.position = CGPointMake(KClockRadius, KClockRadius);
_hourLayer.bounds = CGRectMake(0, 0, 4, KClockRadius-45);
_hourLayer.cornerRadius = 4;
}
return _hourLayer;
}
刷新状态:
使用NSCalendar获取当前时分秒,开启一个NSTimer,每秒刷新时分秒针的状态,代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
[self.clockImageView.layer addSublayer:self.hourLayer];
[self.clockImageView.layer addSublayer:self.minuteLayer];
[self.clockImageView.layer addSublayer:self.secondLayer];
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChanged) userInfo:nil repeats:YES];
//为了保证程序一运行,时分秒针就在当前时间的位置,需先手动调用下刷新的方法
[self timeChanged];
}
- (void)timeChanged {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond |NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
self.secondLayer.transform = CATransform3DMakeRotation(KAngle2Radian(cmp.second * KPerSecondA), 0, 0, 1);
self.minuteLayer.transform = CATransform3DMakeRotation(KAngle2Radian(cmp.minute * KPerMinuteA), 0, 0, 1);
self.hourLayer.transform = CATransform3DMakeRotation(KAngle2Radian(cmp.hour * KPerHourA + cmp.minute * KPerMinuteHourLA), 0, 0, 1);
self.timeLabel.text = [NSString stringWithFormat:@"%.2ld:%.2ld:%.2ld", cmp.hour, cmp.minute, cmp.second];
}
Demo的github地址:https://github.com/mws100/ClockExample.git
各位有更好的实现思路可留言讨论。