美文网首页iOS开发iOS精英班知识点
iOS动画系列之二:带时分秒指针的时钟动画(下)

iOS动画系列之二:带时分秒指针的时钟动画(下)

作者: 非典型技术宅 | 来源:发表于2017-02-04 09:09 被阅读2682次

好了,书接上文。上文地址:http://www.jianshu.com/p/26a7ccbc55c4

动画这个系列大概会分享五篇文章,但是也有可能因为自己偷懒或者其他缘故改变一下。Hoho~

-----------------------华丽分割线,iOS动画系列全集链接-------------------------------------------------
第一篇:iOS动画系列之一:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画(上)
第二篇:iOS动画系列之二:通过实战学习CALayer和透视的原理。做一个带时分秒指针的时钟动画。包含了OC和Swift两种源代码(下)
第三篇:iOS动画系列之三:Core Animation。介绍了Core Animation的常用属性和方法。
第四篇:CABasic Animation。iOS动画系列之四:基础动画之平移篇
第五篇:CABasic Animation。iOS动画系列之五:基础动画之缩放篇&旋转篇
第六篇:iOS动画系列之六:利用CABasic Animation完成带动画特效的登录界面
第七篇:iOS动画系列之七:实现类似Twitter的启动动画
第八篇:iOS动画系列之八:使用CAShapeLayer绘画动态流量图
第九篇:iOS动画系列之九:实现点赞的动画及播放起伏指示器
第十篇:实战系列:绘制过山车场景

被自己的任性感动哭了,哈哈~了解了CALayer的一些基本属性之后,我们开始~~撸管~~撸起袖子敲代码了。

任性君又突发奇想,把这份代码用Objective-C和Swift都敲了一遍。文后面给了两个版本的源代码下载地址。

1. 创建CALayer

  • position:默认情况下相当于UIView的center
  • contents:CALayer的内容。可以设置为图片,但是需要桥接。桥接不需要自己额外设置,编译后编译器会自动提示,让Xcode自动帮我们桥接就可以啦。
  • 就像添加子视图一样,别忘了把自己创建的Layer添加到view.layer上面。
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CALayer *dialLayer= [[CALayer alloc] init];
    dialLayer.bounds = CGRectMake(0, 0, 150, 150);
    
    dialLayer.position = self.view.center;
    
    dialLayer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"clock"].CGImage);
    
    [self.view.layer addSublayer:dialLayer];
}

2. 设置时分秒针

以秒针为例。时针、分针都是一样的。

//    设置秒针
    UIView *secondHandView = [[UIView alloc]init];
    secondHandView.backgroundColor = [UIColor redColor];
    secondHandView.bounds = CGRectMake(0, 0, 1, 60);
    secondHandView.center = self.view.center;
    
    
//    修改锚点
    secondHandView.layer.anchorPoint = CGPointMake(0.5, 1);
    [self.view addSubview:secondHandView];
    self.secondHandView = secondHandView;

锚点是个神马东东?

锚点是神马吶?打个比方,我们耍双截棍的时候,双截棍其实都是围绕咱们握拳的地方转来转去的,👊其实就是双截棍的锚点。

再打个比方,我们在一张A4纸上面钉一个📌。然后旋转A4纸,那颗图钉的位置就是A4纸的锚点。

所以锚点肯定是个坐标点喽~有X、Y组成。锚点的数值范围就是0~1。0表示在最左边或者最上边,1表示在最右边或者最下边。有点模糊是不?再来张图就更清楚了:

锚点示意图1.png 锚点示意图2.png

咱们刚才绘制的秒针实际就是一个宽1,长60的一个View。咱们要让它旋转起来的时候围绕着一个点转,就要把那个点用图钉钉上。这个图钉的位置就是锚点,就是我们在代码中设置的(0.5,1).

3. 创建CADisplayLink

我们一开始想到的办法就是用定时器,每一秒钟刷新一次秒针。但是使用了定时器之后,有一个问题。发现秒针比电脑上的稍微慢一点。是因为刷新频率和电脑不一样。

  • 解决方法就是使用CADisplayLink来刷新时钟。
//    创建CADisplayLink
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(clockRunning)];
//    将创建的CADisplayLink加入到主线程中
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

3.1 CADisplayLink和NSTimer的区别

  • NSTimer占用系统资源较多
  • NSTimer使用完后,一定要销毁,把它设置成nil。
  • CADisplayLink本来就在进程中,每秒进行60次。
  • 核心动画的时候,最好使用CADisplayLink

3.2 获取时间及时区

  • clockRunning这个方法中,我们要设置时区,获取日历、当前时间。

在和时间打交道的时候,请千万别忘记了时区。全球有那么多国家,不要只想着自己哈。

//获取本地时区
    NSTimeZone *tZone = [NSTimeZone localTimeZone];

//    获取日历
    NSCalendar *calendar = [NSCalendar currentCalendar];
    
//获取系统当前时间    
    NSDate *currentDate = [NSDate date];
 //设置日历的时区   
    [calendar setTimeZone:tZone];
//取出当前的时分秒
    NSDateComponents *currentTime = [calendar components:NSCalendarUnitSecond|NSCalendarUnitMinute|NSCalendarUnitHour|NSCalendarUnitTimeZone fromDate:currentDate];
  

3.3 根据当前时间计算时分秒针弧度

根据当前时间计算时分秒针弧度,然后让自己设置的View进行形变。

因为咱们这个方法是通过CADisplayLink来调用的,也就是说一分钟会被调用60次。因此每秒咱们的秒针都会旋转一次。

    CGFloat angle = (M_PI * 2 / 60) * currentTime.second;
    
    self.secondHandView.transform = CGAffineTransformMakeRotation(angle);
    
    CGFloat minuteAngle = (M_PI * 2 / 60) * currentTime.minute;
    self.minuteHandView.transform = CGAffineTransformMakeRotation(minuteAngle);
    
    CGFloat hourAngle = (M_PI * 2 / 12) * currentTime.hour;
    self.hourHandView.transform = CGAffineTransformMakeRotation(hourAngle);

4. 成稿

完成效果:

Paste_Image.png

OC和Swift的下载地址如下:
https://git.oschina.net/atypical/clock.git

iOS实践:带时分秒指针的时钟动画(OC和Swift两版)

相关文章

网友评论

  • 溜溜leesin:设置anchorPoint之后,是不是相应的view的位置发生了变化?如果不设置anchorPoint那么view是围绕自身的center进行旋转,设置锚点后,view旋转中心发生了变化。另,这个锚点设置为(0.5,0)或者(0.5,1)都是一样的。
  • 梵高的老巫婆:我想问下 秒针分针时针现在末端都交叉在一个点了不太好看 怎么实现那种各个针都留出一小段的那种
    非典型技术宅:@梵高的老巫婆 锚点
  • Yaanco:你好,时分秒这三个针可以使用layer吗,它们有什么区别呢?我测试了一下,针摆动的效果好像有点差别
    非典型技术宅:@单线程 layer 是可以的。UIview 其实最终还是依靠layer 显示
  • 开发者头条_程序员必装的App:感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/hsfnqe 欢迎点赞支持!
    欢迎订阅《非典型技术宅》https://toutiao.io/subjects/247733
  • 李潇南:你好这有个很明显的BUG,不知道您有什么思路吗? 比如:下午2:30,我们实际情况的时针是应该指向2个数字之间的,而不是直接指向2这个数字。望回复!
    DylanPP:@李潇南 CGFloat hourAngle = (M_PI * 2 / 12) * (currentTime.hour+currentTime.minute/60.0);
    李潇南:@非典型技术宅 谢谢
    非典型技术宅:@李潇南 时针计算到2这个数字,然后加上分针2~3的偏移量就好了。例如2:45,STEP1:先计算出来2点应该在的弧度A。STEP2:计算分针45应该在的弧度B。STEP3:对于时针而言,每个小时的弧度只有180/12 = 15度。用(弧度B / 180 )* 15,就可以得到时针的偏移弧度C。STEP4:弧度A + 弧度C就是最终时针的准确位置了。
  • 欧阳铨:CADisplayLink并不是一定会每60秒刷新一次哦:smirk:
    小_菜_鸟:时钟一秒刷新一次就可以了吧
    CADisplayLink每秒刷新60 用到这里有点太快了吧
    非典型技术宅:这个要看FPS是多少,如果屏幕刷新频率更高,CADisplayLink刷新的频率更快。但是一般上iOS设备的FPS是60HZ,所以通常CADisplayLink是每秒刷新60次。
  • Rickie_Lambert:链接跳转到 码云, 里面项目 什么都没有, 你上传错了项目把
    叶先森_iOS_前端:确实啥也没有!
    Rickie_Lambert:@非典型技术宅 下载下来后,里面的项目是个空工程
    非典型技术宅:检查了一下,确实有啊。项目里面有两个目录,一个是Clock这个是OC的。另外一个是ClockSwift,这个是swift的。

本文标题:iOS动画系列之二:带时分秒指针的时钟动画(下)

本文链接:https://www.haomeiwen.com/subject/kdtjittx.html