一:隐式动画

#import "ViewController.h"

@interface ViewController ()

/** <#注释#> */
@property (nonatomic, weak) CALayer *layer;
@property (weak, nonatomic) IBOutlet UIView *redView; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; CALayer *layer = [CALayer layer];
layer.backgroundColor = [UIColor redColor].CGColor;
layer.frame = CGRectMake(, , , );
self.layer = layer;
[self.view.layer addSublayer:layer]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //只有非根层才有隐式动画,(自己手动创建的图片)
[CATransaction begin];
[CATransaction setDisableActions:NO];//此属性可设置关掉隐士动画
[CATransaction setAnimationDuration:];
self.layer.backgroundColor = [UIColor greenColor].CGColor;
[CATransaction commit]; self.layer.bounds = CGRectMake(, , , );
self.layer.backgroundColor = [UIColor greenColor].CGColor;
self.layer.position = CGPointMake(, ); self.redView.layer.position = CGPointMake(, );
self.redView.layer.bounds = CGRectMake(, , , );
self.redView.layer.backgroundColor = [UIColor greenColor].CGColor; } @end

什么是隐式动画?

了解什么是隐式动画前,要先了解是什么根层和非根层.

根层:UIView内部自动关联着的那个layer我们称它是根层.

非根层:自己手动创建的层,称为非根层.

隐式动画就是当对非根层的部分属性进行修改时, 它会自动的产生一些动画的效果.

我们称这个默认产生的动画为隐式动画.

如何取消隐式动画?

首先要了解动画底层是怎么做的.动画的底层是包装成一个事务来进行的.

什么是事务?

很多操作绑定在一起,当这些操作执行完毕后,才去执行下一个操作.

开启事务

[CATransaction begin];

设置事务没有动画

[CATransaction setDisableActions:YES];

设置动画执行的时长

[CATransaction setAnimationDuration:2];

提交事务

[CATransaction commit];

二:时钟效果:

效果如图:

#import "ViewController.h"

//每一秒旋转的度数
#define perSecA 6 //每一分旋转的度数
#define perMinA 6 //每一小时旋转的度数
#define perHourA 30 //每一分,时针旋转的度数
#define perMinHour 0.5 #define angle2Rad(angle) ((angle) / 180.0 * M_PI) @interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *colockView; /** 当前的秒针 */
@property (nonatomic, weak) CALayer *secL;
/** 当前的分针 */
@property (nonatomic, weak) CALayer *minL;
/** 当前的针针 */
@property (nonatomic, weak) CALayer *hourL; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; //添加时针
[self setHour]; //添加分针
[self setMin];
//添加秒针
[self setSec]; //添加定时器:scheduledTimerWithTimeInterval不用加到runLoop,因为已经默认添加到了runLoop
[NSTimer scheduledTimerWithTimeInterval: target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
//添加的定时器不会立即执行,而是过一秒才会执行,此时可以调用定时器的fire方法,立即执行,也可以手动调用定时器的方法
[self timeChange];
} //第一称调用一次
- (void)timeChange { NSCalendar *cal = [NSCalendar currentCalendar];
//components:日历的组件,年,月,日 ,时,分,秒.
//fromDate:从什么时间开始获取
NSDateComponents *cmp = [cal components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
//获取当前多少秒
NSInteger curSec = cmp.second + ; //秒针开始旋转
//计算秒针当前旋转的角度.
//angle = 当前多少秒 * 每一秒旋转多少度.
/**
* CATransform3DMakeRotation:3D旋转:1:必须是在layear层才能进行3D旋转,用transform,旋转的角度为弧度制,2:#define angle2Rad(angle) ((angle) / 180.0 * M_PI) 3:分xyz轴,
*/
CGFloat secA = curSec * perSecA;
self.secL.transform = CATransform3DMakeRotation(angle2Rad(secA), , , ); //获取当前多少秒
NSInteger curMin = cmp.minute;
NSLog(@"%ld",curMin);
//分针开始旋转
//计算分针当前旋转的角度.
//angle = 当前多少分 * 每一分旋转多少度.
CGFloat minA = curMin * perMinA;
self.minL.transform = CATransform3DMakeRotation(angle2Rad(minA), , , ); //获取当前是多少小时
NSInteger curHour = cmp.hour;
NSLog(@"%ld",curMin);
//分针开始旋转
//计算分针当前旋转的角度.
//angle = 当前多少小时 * 每一小时旋转多少度.
CGFloat hourA = curHour * perHourA + curMin * perMinHour;
self.hourL.transform = CATransform3DMakeRotation(angle2Rad(hourA), , , ); } /**
* 1:搭建时针秒针分针的UI效果:1:UIView和CALayear是一样的效果,但是UIView比CALyear多了一个处理点击事件,则CALyear相对于UIView来说更加轻量级,更加高效 2:非根层的layear也就是自己创建的layear都存在隐士动画,要关闭隐式动画,用动画事物CATransaction去关闭:
开启事务 [CATransaction begin]; 设置事务没有动画 [CATransaction setDisableActions:YES]; 设置动画执行的时长 [CATransaction setAnimationDuration:2]; 提交事务 [CATransaction commit]; 3:无论是旋转,缩放都是绕着锚点进行的.也就是默认情况下是绕着中心点center进行的。所以要改变其绕着最后的节点旋转,需要先定义好layear的position,在定义锚点,最后的效果是锚点与point点重合。position的位置为表盘的中心点,锚点的默认位置为0.5 ,0.5,修改表盘的锚点位置让锚点与position点重合,这样旋转的时候就会绕着锚点旋转。再把此layear添加到表盘的layear上。
*
*
*/ //添加秒针
//无论是旋转,缩放都是绕着锚点进行的.
- (void)setSec { CALayer *secL = [CALayer layer];
secL.bounds = CGRectMake(, , , );
secL.backgroundColor = [UIColor redColor].CGColor;
secL.anchorPoint = CGPointMake(0.5, );
secL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
[self.colockView.layer addSublayer:secL];
self.secL = secL; } //添加分针
- (void)setMin { CALayer *minL = [CALayer layer];
minL.bounds = CGRectMake(, , , );
minL.backgroundColor = [UIColor blackColor].CGColor;
minL.anchorPoint = CGPointMake(0.5, );
minL.cornerRadius = 1.5;
minL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
[self.colockView.layer addSublayer:minL];
self.minL = minL; } //时针
- (void)setHour { CALayer *hourL = [CALayer layer];
hourL.bounds = CGRectMake(, , , );
hourL.backgroundColor = [UIColor blackColor].CGColor;
hourL.anchorPoint = CGPointMake(0.5, );
hourL.cornerRadius = 1.5;
hourL.position = CGPointMake(self.colockView.bounds.size.width * 0.5, self.colockView.bounds.size.height * 0.5);
[self.colockView.layer addSublayer:hourL];
self.hourL = hourL; } //-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//
// //所有旋转,缩放,都是绕着锚点进行.
// self.secL.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
//} @end

1.搭建界面.

分析界面.

界面上时针,分针,秒针不需要与用户进行交互.所以都可以使用layer方式来做.

做之前要观察时针在做什么效果.

是根据当前的时间,绕着表盘的中心点进行旋转.

要了解一个非常重要的知识点.无论是旋转,缩放它都是绕着锚点.进行的.

要想让时针,分针,称针显示的中间,还要绕着中心点进行旋转.

那就要设置它的position和anchorPoint两个属性.

创建秒针

CALayer *layer = [CALayer layer];

_secLayer = layer;

layer.bounds = CGRectMake(0, 0, 1, 80);

layer.anchorPoint = CGPointMake(0.5, 1);

layer.position = CGPointMake(_clockView.bounds.size.width * 0.5, _clockView.bounds.size.height * 0.5);

layer.backgroundColor = [UIColor redColor].CGColor;

[_clockView.layer addSublayer:layer];

2.让秒针开始旋转.

让秒针旋转.所以要计算当前的旋转度是多少?

当前的旋转角度为:当前的时间 * 每秒旋转多少度.

计算每一秒旋转多少度.

60秒转一圈360度

360 除以60就是每一秒转多少度.每秒转6度.

获取当前的时间

创建日历类

NSCalendar *calendar = [NSCalendar currentCalendar];

把日历类转换成一个日期组件

日期组件(年,月,日,时,分,秒)

component:日期组件有哪些东西组成,他是一个枚举,里面有年月日时分秒

fromDate:当前的日期

NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond

fromDate:[NSDate date]];

我们的秒就是保存在日期组件里面,它里面提供了很多get方法.

NSInteger second = cmp.second;

那么当前秒针旋转的角度就是

当前的秒数乘以每秒转多少度.

second * perSecA

还得要把角度转换成弧度.

因为下面分针,时针也得要用到, 就把它抽出一个速参数的宏.

#define angle2Rad(angle) ((angle) / 180.0 * M_PI)

让它每隔一秒旋转一次.所以添加一个定时器.

每个一秒就调用,旋转秒针

- (void)timeChange{

获取当前的秒数

创建日历类

NSCalendar *calendar = [NSCalendar currentCalendar];

把日历类转换成一个日期组件

日期组件(年,月,日,时,分,秒)

component:日期组件有哪些东西组成,他是一个枚举,里面有年月日时分秒

fromDate:当前的日期

NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond

fromDate:[NSDate date]];

我们的秒就是保存在日期组件里面,它里面提供了很多get方法.

NSInteger second = cmp.second;

秒针旋转多少度.

CGFloat angel = angle2Rad(second * perSecA);

旋转秒针

self.secondL.transform = CATransform3DMakeRotation(angel, 0, 0, 1);

}

运行发现他会一下只就调到某一个时间才开始旋转

一开始的时候就要来到这个方法,获取当前的秒数把它定位好.

要在添加定时器之后就调用一次timeChange方法.

3.添加分针

快速拷贝一下,然后添加一个分针成员属性.

修改宽度,修改颜色

也得要让它旋转,

要算出每分钟转多少度

转60分钟刚好是一圈

所以每一分钟也是转6度.

获取当前多少分?

同样是在日期组件里面获得

里面有左移符号,右移符号.他就可以用一个并运算

现在同时让他支持秒数和分 后面直接加上一个 |

NSDateComponents *cmp = [calendar components:NSCalendarUnitSecond |

NSCalendarUnitMinute

fromDate:[NSDate date]];

CGFloat minueteAngel = angle2Rad(minute * perMinuteA);

self.minueL.transform = CATransform3DMakeRotation(minueteAngel, 0, 0, 1);

4.添加时针

同样复制之前的,添加一个小时属性

小时转多少度

当前是多少小时,再计算先每一小时转多少度.

12个小时转一圈. 360除以12,每小时转30度

时针旋转多少度

CGFloat hourAngel = angle2Rad(hour * perHourA);

旋转时针

self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);

直接这样写会有问题

就是没转一分钟,小时也会移动一点点

接下来要算出,每一分钟,小时要转多少度

60分钟一小时.一小时转30度.

30 除以60,就是每一分钟,时针转多少度.0.5

时针旋转多少度

CGFloat hourAngel = angle2Rad(hour * perHourA + minute * perMinuteHourA);

旋转时针

self.hourL.transform = CATransform3DMakeRotation(hourAngel, 0, 0, 1);

ios开发核心动画三:隐式动画与时钟效果的更多相关文章

  1. iOS动画学习 -隐式动画

    事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.你并不需要在Core Animation中手动打开动画,但是你需要明确地关闭它,否则它会一直存在. 当你改变 ...

  2. iOS:CALayer的隐式动画的详解

    CALayer的隐式动画属性: •每一个UIView内部都默认关联着一个CALayer,称这个Layer为Root Layer.所有的非Root Layer都存在着隐式动画,隐式动画的默认时长为1/4 ...

  3. iOS中的隐式动画

    隐式动画就是指  在 非 人为在代码中 定义动画  而系统却默认  自带   的动画  叫做隐式动画. 比如  改变 图层  的颜色  位置  和   透明度  的时候    都会  产生附带的渐变的 ...

  4. [iOS Animation]-CALayer 隐式动画

    隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画是Core Animation库一个非常显著的 ...

  5. iOS边练边学--CALayer,非根层隐式动画,钟表练习

    一.CALayer UIView之所以能显示在屏幕上,完全是因为他内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性 ...

  6. IOS第18天(3,CALayer隐式动画)

    ******隐式动画(手指拖拽Layer) #import "HMViewController.h" @interface HMViewController () @propert ...

  7. IOS 隐式动画(非Root Layer)

    ● 每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根 层) ● 所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动 ...

  8. CALayer的隐式动画

    CALayer的使用 在我的理解中CALayer就是iOS中利用图层精简非交互式绘图.那么那些核心动画类.也就是变化图层的非交互式绘制规则而已.其中的本质就是将CALayer中的内容转化为map图.从 ...

  9. 非RootLayer的隐式动画

    非RootLayer都有隐式动画,默认0.25秒. // 1.开启 [CATransaction begin]; // 2.设置关闭 YES-关闭:NO-开启 [CATransaction setDi ...

随机推荐

  1. [Redux-Observable && Unit Testing] Use tests to verify updates to the Redux store (rxjs scheduler)

    In certain situations, you care more about the final state of the redux store than you do about the ...

  2. 数据存储值归档Archive

    先比較一下各个数据存储之间的关系: 关于归档.是ios中的shu'j数据存储中的一种数据存储方式.以下了解一下归档中的一个实例: 以下的是父类person #import <Foundation ...

  3. Android中关于JNI 的学习(零)简单的样例,简单地入门

    Android中JNI的作用,就是让Java可以去调用由C/C++实现的代码,为了实现这个功能.须要用到Anrdoid提供的NDK工具包,在这里不讲怎样配置了,好麻烦,配置了好久. . . 本质上,J ...

  4. LinearLayout-控件不显示

    今天Mms遇到了一个问题,布局如下             <RelativeLayout                android:layout_width="match_par ...

  5. 1.23 Python知识进阶 - 面向对象编程

    一.编程方法 1.函数式编程:"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论.它属于"结构化 ...

  6. 1.17 Python基础知识 - 迭代器和生成器初识

    可循环迭代的对象称为可迭代对象,迭代器和生成器函数是可迭代对象. 列表解析表达式:可以简单高效处理一个可迭代对象,并生成结果列表 示例代码: [ i ** 2 for i in range(10) ] ...

  7. MySQLSocketPHPvimApache

    原文:http://www.blogjava.net/asenyifei/articles/82575.html 自己装了一个MYSQL客户端,但却发现出现这样的错误: Can't connect t ...

  8. 洛谷 P2640 神秘磁石

    P2640 神秘磁石 题目背景 在遥远的阿拉德大陆,有一种神秘的磁石,是由魔皇制作出来的, 题目描述 1.若给他一个一维坐标系,那么他的磁力一定要在素数坐标的位置上才能发挥的最大(不管位置坐标的大小, ...

  9. Activity启动模式的深入分析

    网上关于Activity启动模式的文章许多.可是看起来都千篇一律,看完之后我们都能理解这4种启动模式.只是官方api对singleTask这个启动模式解释有些争议,导致我事实上并没有真正理解这几种模式 ...

  10. HTML基础第三讲---字体

    转自:https://i.cnblogs.com/posts?categoryid=1121494 同样我们在这里继续讲一下它的body,因为它能直观的让大家观察到你所学到的成果. 这一讲,我们来学习 ...