ios开发-UI进阶-核心动画-时钟动画小案例

  

  [注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/

  

  今天使用CALayer的"定位点(锚点)"实现了一个时钟动画,其实就是一个小的时钟,只是实现了功能,没有做出绚丽的效果.使用UIView实现的,其实只是单纯的使用layer也可以实现.主要用到了 Quartz2D画图\ 事件处理\核心动画方面的知识.

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

  下图为应用截图,使用gif,没有制作好,见谅哈.

  

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

  

  下面附上源代码:

  viewController.m

  

  1 //
  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;
120     angleHour = hours *angleHour;
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中的日期时间的每一部分
  • 进行旋转,完毕!

获取当前系统中的时间的某一部分的方法

 1 //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并不是永远表示控件的中心点。

  

CALayer有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 : 显示内容

  

时间: 06-12

ios开发-UI进阶-核心动画-时钟动画小案例的相关文章

iOS开发UI篇—核心动画(基础动画)

iOS开发UI篇—核心动画(基础动画) 一.简单介绍 CAPropertyAnimation的子类 属性解析: fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue 如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态.但

iOS开发UI篇—核心动画(转场动画和组动画)

iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果 属性解析: type:动画过渡类型 subtype:动画过渡方向 startProgress:动画起点(在整体动画的百分比) endProgress:动画终点(在整体动画的百分比)

iOS开发UI篇—核心动画(关键帧动画)

iOS开发UI篇—核心动画(关键帧动画) 一.简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值 属性解析: values:就是上述的NSArray对象.里面的元素称为”关键帧”(keyframe).动画对象会在指定的时间(duration)内,依次显示values数组

iOS开发UI篇—核心动画简介

iOS开发UI篇—核心动画简介 一.简单介绍 Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core Animation是跨平台的,可以用在Mac OS X和iOS平台. Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程.不阻塞主线程,可以理解为在执行动画的时候还能点击(按钮). 要注意的是,Core Animation是直接作用

iOS开发UI篇—核心动画(转场动画和组动画)(转摘)

iOS开发UI篇—核心动画(转场动画和组动画) 一.转场动画简单介绍 CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果 属性解析: type:动画过渡类型 subtype:动画过渡方向 startProgress:动画起点(在整体动画的百分比) endProgress:动画终点(在整体动画的百分比)

iOS开发UI篇—核心动画(关键帧动画)(转摘)

iOS开发UI篇—核心动画(关键帧动画) 一.简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值 属性解析: values:就是上述的NSArray对象.里面的元素称为”关键帧”(keyframe).动画对象会在指定的时间(duration)内,依次显示values数组

iOS开发UI篇—核心动画(UIView封装动画)(转摘)

iOS开发UI篇—核心动画(UIView封装动画) 一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持 执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIViewbeginAnimations:nil context:nil]和[UIView commitAnimations]之间 常见方法解析: + (void)setAnimati

iOS开发UI篇—实现一个私人通讯录小应用(一) - 文顶顶

原文  http://www.cnblogs.com/wendingding/p/3773603.html iOS开发UI篇—实现一个私人通讯录小应用(一) 一.该部分主要完成内容 1.界面搭建                        2.功能说明 (1).只有当账号和密码输入框都有值的时候,登录按钮才能交互 (2).当取消勾选记住密码后,自动登录按钮也随之取消:当勾选了自动登录按钮时,记住密码按钮也一同勾选. (3).点击登陆后,弹出蒙版,界面不可交互,程序能够简单判断账号和密码是否正确

iOS开发UI篇—实现一个私人通讯录小应用(二)

iOS开发UI篇—实现一个私人通讯录小应用(二) 一.实现功能说明 (1)点击注销按钮,弹出一个对话框,点击确定后移除当前栈顶的控制器,返回开始界面,点击取消,不做任何操作. 注意:注销按钮的单击事件已经进行了连线.实现-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex需要遵守UIActionSheetDelegate协议. 1 //注销按钮 2 - (IBActi