- 论坛徽章:
- 0
|
转载自 吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/
今天使用CALayer的"定位点(锚点)"实现了一个时钟动画,其实就是一个小的时钟,只是实现了功能,没有做出绚丽的效果.使用UIView实现的,其实只是单纯的使用layer也可以实现.主要用到了 Quartz2D画图\ 事件处理\核心动画方面的知识.
代码不是很多,直接附上源码,注释比较详细,在源码后面再进行解释其中的一些知识点和注意点.
下图为应用截图,使用gif,没有制作好,见谅哈.[此处图片有一点小问题,时间显示正常,指针处有点问题,代码中修改过来了
下图为模拟器与电脑时间对比图,和正常时间一样.
下面附上源代码:
viewController.m- //
- 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.
主要思路就是:
设置view的背景
创建一个表示表盘的view,设置表盘view的大小和位置,在contents属性中设置图片,根据圆角半径的知识,使用masksToBounds进行剪切,将这个view加到控制器的view中
分别创建一个秒针\分针\时针的view,分别设置大小和位置,设置颜色,等属性,分别将view加入到控制器的view中.
创建一个CADisplayLink对象,(CADisplayLink能提供一个周期性调用赋值给它的selector的机制,很像定时器NSTimer)
实现上述CADisplayLink对象中添加的move方法
在move方法中,计算所转的弧度,通过日历牌对象(NSCalender),获取NSDate中的日期时间的每一部分
进行旋转,完毕!
获取当前系统中的时间的某一部分的方法- //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并不是永远表示控件的中心点。
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的一些属性- //宽度和高度
- @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 : 接受和处理系统事件、触摸事件。
CALayer : 显示内容 |
|