免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3232 | 回复: 0
打印 上一主题 下一主题

[iOS] ios开发-UI进阶-核心动画-时钟动画小案例 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-16 09:44 |只看该作者 |倒序浏览
转载自   吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/
今天使用CALayer的"定位点(锚点)"实现了一个时钟动画,其实就是一个小的时钟,只是实现了功能,没有做出绚丽的效果.使用UIView实现的,其实只是单纯的使用layer也可以实现.主要用到了 Quartz2D画图\ 事件处理\核心动画方面的知识.

  代码不是很多,直接附上源码,注释比较详细,在源码后面再进行解释其中的一些知识点和注意点.

  下图为应用截图,使用gif,没有制作好,见谅哈.[此处图片有一点小问题,时间显示正常,指针处有点问题,代码中修改过来了

下图为模拟器与电脑时间对比图,和正常时间一样.

下面附上源代码:

  viewController.m
  1. //
  2.   2 //  ViewController.m
  3.   3 //  01-时钟动画time
  4.   4 //
  5.   5 //  Created by hukezhu on 15/6/12.
  6.   6 //  Copyright (c) 2015年 hukezhu. All rights reserved.
  7.   7 //
  8.   8
  9.   9 #import "ViewController.h"
  10. 10
  11. 11 @interface ViewController ()
  12. 12 //秒针view
  13. 13 @property(nonatomic,strong)UIView *secondView;
  14. 14 //分针view
  15. 15 @property(nonatomic,strong)UIView *minView;
  16. 16 //时针view
  17. 17 @property(nonatomic,strong)UIView *hourView;
  18. 18 @end
  19. 19
  20. 20 @implementation ViewController
  21. 21
  22. 22 - (void)viewDidLoad {
  23. 23     [super viewDidLoad];
  24. 24     //设置背景颜色
  25. 25     self.view.backgroundColor = [UIColor greenColor];
  26. 26     
  27. 27     //创建一个表盘view
  28. 28     UIView *clockView = [[UIView alloc]init];
  29. 29     //设置位置
  30. 30     clockView.center = self.view.center;
  31. 31     //设置大小
  32. 32     clockView.layer.bounds = CGRectMake(0, 0, 214, 214);
  33. 33     
  34. 34     //设置显示内容
  35. 35     clockView.layer.contents = (__bridge id)([UIImage imageNamed:@"clock1"].CGImage);
  36. 36     //设置圆角半径
  37. 37     clockView.layer.cornerRadius = 107;
  38. 38     //设置裁剪
  39. 39     clockView.layer.masksToBounds = YES;
  40. 40     //将clockView添加到控制器view中
  41. 41     [self.view addSubview:clockView];
  42. 42     
  43. 43     
  44. 44     
  45. 45     
  46. 46     //创建一个秒针view
  47. 47     UIView *secondView = [[UIView alloc]init];
  48. 48     secondView.center = clockView.center;
  49. 49     secondView.layer.bounds = CGRectMake(0, 0, 2, 90);
  50. 50     secondView.layer.backgroundColor = [UIColor redColor].CGColor;
  51. 51     secondView.layer.anchorPoint = CGPointMake(0.5, 1);
  52. 52     
  53. 53     self.secondView = secondView;
  54. 54     [self.view addSubview:secondView];
  55. 55     
  56. 56     
  57. 57     
  58. 58     //创建一个分针view
  59. 59     UIView *minView = [[UIView alloc]init];
  60. 60     minView.center = clockView.center;
  61. 61     minView.layer.bounds = CGRectMake(0, 0, 4, 70);
  62. 62     minView.layer.backgroundColor = [UIColor blueColor].CGColor;
  63. 63     minView.layer.anchorPoint = CGPointMake(0.5, 1);
  64. 64
  65. 65     self.minView = minView;
  66. 66     [self.view addSubview:minView];
  67. 67     
  68. 68     
  69. 69     
  70. 70     //创建一个时针view
  71. 71     UIView *hourView = [[UIView alloc]init];
  72. 72     hourView.center = clockView.center;
  73. 73     hourView.layer.bounds = CGRectMake(0, 0, 6, 50);
  74. 74     hourView.layer.backgroundColor = [UIColor blackColor].CGColor;
  75. 75     hourView.layer.anchorPoint = CGPointMake(0.5, 1);
  76. 76     
  77. 77     self.hourView = hourView;
  78. 78     [self.view addSubview:hourView];
  79. 79     
  80. 80
  81. 81     // 开启一个计时器控件
  82. 82     //NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(move) userInfo:nil repeats:YES];
  83. 83     //创建一个对象
  84. 84     CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(move)];
  85. 85     //启动这个link
  86. 86     [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
  87. 87 }
  88. 88
  89. 89
  90. 90 - (void)move{
  91. 91
  92. 92     
  93. 93     //1.计算对应的弧度
  94. 94     CGFloat angle = M_PI * 2 / 60.0;
  95. 95     CGFloat angleMin = M_PI * 2 / 60.0;
  96. 96     CGFloat angleHour = M_PI * 2 / 12.0 ;
  97. 97     
  98. 98     //2.获取当前事件
  99. 99     NSDate *date = [NSDate date];
  100. 100     
  101. 101     //创建一个日历牌对象(NSCalender),通过这个对象才能获取NSDate中的日期时间的每一部分
  102. 102     NSCalendar *calender = [NSCalendar currentCalendar];
  103. 103     
  104. 104     //告诉日历牌对象,需要获取哪些部分的值
  105. 105     
  106. 106     //取得当前的秒
  107. 107     NSInteger secs = [calender component:NSCalendarUnitSecond fromDate:date];
  108. 108     //取得当前的分
  109. 109     NSInteger mins = [calender component:NSCalendarUnitMinute fromDate:date];
  110. 110     //取得当前的时
  111. 111     NSInteger hours = [calender component:NSCalendarUnitHour fromDate:date];
  112. 112     
  113. 113     
  114. 114     //NSLog(@"%zd,%zd,%zd",hours,mins,secs);//测试用
  115. 115     
  116. 116     
  117. 117     //计算本次旋转应该旋转到的弧度数
  118. 118     angle = secs *angle;
  119. 119     angleMin = mins *angleMin + angle/60.0;
  120. 120     angleHour = hours *angleHour + angleMin/12.0  ;
  121. 121
  122. 122     //让时分秒针旋转
  123. 123     self.secondView.transform = CGAffineTransformMakeRotation(angle);
  124. 124     self.minView.transform = CGAffineTransformMakeRotation(angleMin);
  125. 125     self.hourView.transform = CGAffineTransformMakeRotation(angleHour);
  126. 126
  127. 127 }
  128. 128
  129. 129 @end
复制代码
当然,这里面的表盘使用的时图片,我们也可以自己画出来,但是此处有图片资源,就直接使用了.(注意需要剪切图片为圆形,当然,有方形的表盘,但是此处是圆形表盘,所以将图片切割成圆形).

  注意:可以使用NSTimer创建一个定时器,但是通过 NSTimer 实现的动画可能造成卡顿、不连贯的情况(NSTimer 不准确),此处使用CADisplayLink.



  主要思路就是:

设置view的背景
创建一个表示表盘的view,设置表盘view的大小和位置,在contents属性中设置图片,根据圆角半径的知识,使用masksToBounds进行剪切,将这个view加到控制器的view中
分别创建一个秒针\分针\时针的view,分别设置大小和位置,设置颜色,等属性,分别将view加入到控制器的view中.
创建一个CADisplayLink对象,(CADisplayLink能提供一个周期性调用赋值给它的selector的机制,很像定时器NSTimer)
实现上述CADisplayLink对象中添加的move方法
在move方法中,计算所转的弧度,通过日历牌对象(NSCalender),获取NSDate中的日期时间的每一部分
进行旋转,完毕!
获取当前系统中的时间的某一部分的方法
  1. //2.获取当前事件
  2. 2     NSDate *date = [NSDate date];
  3. 3     
  4. 4     //创建一个日历牌对象(NSCalender),通过这个对象才能获取NSDate中的日期时间的每一部分
  5. 5     NSCalendar *calender = [NSCalendar currentCalendar];
  6. 6     
  7. 7     //告诉日历牌对象,需要获取哪些部分的值
  8. 8     
  9. 9     //取得当前的秒
  10. 10     NSInteger secs = [calender component:NSCalendarUnitSecond fromDate:date];
  11. 11     //取得当前的分
  12. 12     NSInteger mins = [calender component:NSCalendarUnitMinute fromDate:date];
  13. 13     //取得当前的时
  14. 14     NSInteger hours = [calender component:NSCalendarUnitHour fromDate:date];
  15. 15     
  16. 16     
  17. 17     //NSLog(@"%zd,%zd,%zd",hours,mins,secs);//测试用
复制代码
知识点:

   注意: 在使用 Quartz2D 绘图的时候, 对绘图上下文的旋转是对坐标系的旋转, 通过 UI 控件的 transform 对控件做旋转是按照 Center 来旋转的。
   注意: 控件的 center 属性, 其实就是对应的 CALayer的 postion。所以控件的 center并不是永远表示控件的中心点。
ALayer有2个非常重要的属性:position和anchorPoint
    position:
      @property CGPoint position;
      用来设置CALayer在父层中的位置
      以父层的左上角为原点(0, 0)


    anchorPoint:
      @property CGPoint anchorPoint;
      称为“定位点”、“锚点”
      决定着CALayer的position属性所指的是哪个点
      以自己的左上角为原点(0, 0)
      它的x、y取值范围都是0~1,默认值为(0.5, 0.5)


CALayer:
    

    UIView之所以能显示在屏幕上,完全是因为它内部的一个图层
    
    在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
     1 @property(nonatomic,readonly,retain) CALayer *layer;  
    
    当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成    了UIView的显示.

    CALayer的一些属性
  1. //宽度和高度
  2. @property CGRect bounds;

  3. //位置(默认指中点,具体由anchorPoint决定)
  4. @property CGPoint position;

  5. //锚点(x,y的范围都是0-1),决定了position的含义
  6. @property CGPoint anchorPoint;

  7. //背景颜色(CGColorRef类型)
  8. @property CGColorRef backgroundColor;

  9. //形变属性
  10. @property CATransform3D transform;

  11. //边框颜色(CGColorRef类型)
  12. @property CGColorRef borderColor;

  13. //边框宽度
  14. @property CGFloat borderWidth;

  15. //圆角半径
  16. @property CGFloat cornerRadius;

  17. //内容(比如设置为图片CGImageRef)
  18. @property(retain) id contents;
复制代码
UIView和CALayer的使用区别:

    UIView : 接受和处理系统事件、触摸事件。

    CALayer : 显示内容
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP