核心动画

Transform field value key paths!

position.x

position.y


1. CALayer1.1.什么是CALayer

是图层。

1.2.CALayer有什么用用来做界面的显示。

1.3.CALayer原理

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图。并且会将所有内容

绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的

显示。

1.4.CALayer的基本使用

阴影shadow

圆角corner

边框border

透明度opacity

背景色backgroundColor内容contents

位置大小frame裁剪maskToBounds

1.5.注意

设置圆角半径不会影响内容,除非剪切。

可以通过拖一个UIImageView组件来检测

1.6.CALayer所属框架,并且介绍类型介绍

数据类型是QuartzCore框架中的。

为了跨平台,跨了哪些平台?

Mac系统 iOS系统

1.7.UIView和CALayer的选择如果显示的东西需要与用户交互,就使用UIView,如果不需要交互就使用CALayer。

CALayer的性能会高一些,因为它少了事件处理功能,更加轻量级。

2.CALayer的bounds,position,anchorPoint属性介绍

bounds设置大小

position显示在父控件中的位置

anchorPoint本身的哪个点与父控件的点重叠。

3. CALayer的隐式动画

非根层的CALayer对象才存在隐式动画。根层CALayer不存在隐式动画

3.1.什么是根层CALayer

也就是UIView的layer属性,这个才是根层的CALayer。自动手动创建添加到CALayer

上的才不是根层layer

4. CALayer的transform属性根层:没有动画,需要自己做一个动画。

需要用KVC做对比。

KVC设置旋转属性在时钟案例中,旋转到30秒的时候会出现问题。

有make和 没有make的区别?

有make:不会叠加效果

没有make:会叠加效果

CATransform3DMakeRotation(angle, x, y, z);

CATransform3DMakeScale(sx, sy, sz);

CATransform3DMakeTranslation(tx, ty, tz);

CATransform3DRotate(transform3D, angle, x, y, z);

CATransform3DScale(transform3D, sx, sy, sz);

CATransform3DTranslate(transform3D, tx, ty, tz);

5. iOS中的时间处理相关类

5.1.NSDate

5.1.1.介绍NSDate是系统时间类

5.1.2.获得系统当前时间

5.2.NSDateFormatter5.2.1.介绍

系统时间格式化类

NSDate*date = [NSDatedate];

5.2.2. NSDate转NSString

NSDate*date = [NSDatedate];

NSDateFormatter*formatter = [[NSDateFormatteralloc]init];

formatter.dateFormat=@"yyyy-MM-dd HH:mm:ss";

NSString*str = [formatterstringFromDate:date];NSLog(@"%@",str);

5.2.3. NSString转NSDate

NSString*time =@"2015-11-29 10:18:07";

NSDateFormatter*formatter = [[NSDateFormatteralloc]init];

formatter.dateFormat=@"yyyy-MM-dd HH:mm:ss";

//设置时区

NSTimeZone*GTMzone = [NSTimeZonetimeZoneForSecondsFromGMT:0];

[formattersetTimeZone:GTMzone];NSDate*date = [formatterdateFromString:time];NSLog(@"%@",date);

5.3.NSCalendar5.3.1.介绍

是系统时间工具类,用于获取时间的各个信息。并且可以做时间比较

5.3.2.获得时间中的时,分,秒等

NSCalendar*calendar = [NSCalendarcurrentCalendar];NSDateComponents*cmp = [calendar

components:NSCalendarUnitSecond fromDate:[NSDatedate]];CGFloatsecond = cmp.second;NSLog(@"%f",second);

6. CALayer时钟案例6.1.背景图片设置

#pragma mark --添加表盘

-(void)addWatch{CALayer*watchLayer = [[CALayeralloc]init];

[self.view.layeraddSublayer:watchLayer];

watchLayer.bounds=CGRectMake(0,0,200,200);

watchLayer.position=

CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2);

watchLayer.anchorPoint=CGPointMake(0.5,0.5);

UIImage*image = [UIImageimageNamed:@"钟表"];

watchLayer.contents= (__bridge id

_Nullable)(image.CGImage);

}

6.2.添加秒针

#pragma mark --添加秒针

-(void)addSecond{CALayer*secondLayer = [[CALayeralloc]init];

[self.view.layeraddSublayer:secondLayer];

secondLayer.bounds=CGRectMake(0,0,1,85);

secondLayer.position=

CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2);

secondLayer.anchorPoint=CGPointMake(0.5,1);

secondLayer.backgroundColor= [UIColorblackColor].CGColor;

self.secondLayer= secondLayer;

}

6.3.添加定时器每秒调用一次

//通过定时器的方式来使 时分秒针旋转起来

-(void)startRun{

[NSTimerscheduledTimerWithTimeInterval:1target:self

selector:@selector(updateTime)userInfo:nilrepeats:YES];

}

6.4.获得当前时间的秒数

//获得一个系统处理时间对象

NSCalendar *calender = [NSCalendar currentCalendar];

//获得 时间对象 来获得当前的 时分秒

NSDateComponents *cmp =[calender

components:NSCalendarUnitSecond fromDate:[NSDate date]];

//秒

CGFloat second = cmp.second;

6.5.旋转秒针

//计算秒针角度

CGFloatangle = (second *6*M_PI) /180;//旋转秒针

self.secondLayer.transform=CATransform3DMakeRotation(angle,0,0,1);

6.6.添加分针

#pragma mark --添加分针

-(void)addMinute{CALayer*minuteLayer = [[CALayeralloc]init];

[self.view.layeraddSublayer:minuteLayer];

minuteLayer.bounds=CGRectMake(0,0,3,70);

minuteLayer.position=

CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2);

minuteLayer.anchorPoint=CGPointMake(0.5,1);

minuteLayer.backgroundColor= [UIColorblackColor].CGColor;

self.minuteLayer= minuteLayer;

}

6.7.获得当前时间的分钟数

//获得一个系统处理时间对象

NSCalendar*calender = [NSCalendarcurrentCalendar];

//获得 时间对象 来获得当前的 时分秒

NSDateComponents*cmp =[calendercomponents:NSCalendarUnitMinute fromDate:[NSDatedate]];

//分

CGFloatminute =cmp.minute;

6.8.旋转分针

//计算分针角度

CGFloatminuteAngle = (minute *6*M_PI) /180;//旋转分针

self.minuteLayer.transform =

CATransform3DMakeRotation(minuteAngle,0,0,1);

6.9.添加时针

#pragma mark --添加时针

-(void)addHour{CALayer*hourLayer = [[CALayeralloc]init];

[self.view.layeraddSublayer:hourLayer];

hourLayer.bounds=CGRectMake(0,0,3,65);

hourLayer.position=

CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2);

hourLayer.anchorPoint=CGPointMake(0.5,1);

hourLayer.backgroundColor= [UIColorcyanColor].CGColor;

self.hourLayer= hourLayer;

}

6.10.获得当前时间的小时

//获得一个系统处理时间对象

NSCalendar*calender = [NSCalendarcurrentCalendar];//获得 时间对象 来获得当前的 时分秒

NSDateComponents*cmp =[calendercomponents:NSCalendarUnitHour fromDate:[NSDatedate]];

//时

CGFloathour =cmp.hour;

6.11.旋转时针

//计算时针角度

CGFloathourAngle = (hour *30*M_PI) /180;CGFloatminute2HourAngle = (minute *0.5*M_PI) /180;

hourAngle += minute2HourAngle;

//旋转时针

self.hourLayer.transform =

CATransform3DMakeRotation(hourAngle,0,0,1);

7.核心动画7.1.动画简介

1.Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做

出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常

强大的功能。

2.Core Animation可以用在Mac OS X和iOS平台。

3.Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。

要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

7.2.核心动画继承结构

7.3.核心动画使用步骤

1.如果不是xcode5之后的版本,使用它需要先添加QuartzCore.framework和引入对应的框架

2.开发步骤:

1.首先得有CALayer

2.初始化一个CAAnimation对象,并设置一些动画相关属性

3.通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer

中,这样就能开始执行动画了

4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

7.4.怎样才能产生动画

事物产生了位移,缩放,旋转,透明度变化,才会产生动画。

所以可动画属性

位置 :position / transform.translation缩放 :transform.scale

旋转 :transform.rotation

透明度 :opacity

7.5.基本动画CABasicAnimation

CABasicAnimation*animation = [CABasicAnimationanimationWithKeyPath:@"position"];

animation.toValue = [NSValue

valueWithCGPoint:CGPointMake(300,350)];

//动画的执行时间

animation.duration =1.0;

//动画的填充模式

animation.fillMode = kCAFillModeForwards;//当动画执行完成后 是否移除

animation.removedOnCompletion =NO;

[self.redLayer addAnimation:animation forKey:key];

7.6.关键帧动画CAKeyframeAnimation

//创建一个关键帧动画

CAKeyframeAnimation*animation = [CAKeyframeAnimationanimation];

animation.keyPath=@"position";

animation.duration=2;

NSValue*value1 = [NSValuevalueWithCGPoint:CGPointMake(50,50)];

NSValue*value2 = [NSValuevalueWithCGPoint:CGPointMake(250,50)];

NSValue*value3 = [NSValuevalueWithCGPoint:CGPointMake(250,300)];

NSValue*value4 = [NSValuevalueWithCGPoint:CGPointMake(50,300)];

animation.values=@[value1,value2,value3,value4,value1];

[self.myLayeraddAnimation:animationforKey:nil];

7.7.动画组CAAnimationGroup

-(void)touchesBegan:(NSSet *)touches

withEvent:(UIEvent*)event{

//移动动画

CABasicAnimation*translate = [CABasicAnimationanimationWithKeyPath:@"position"];

translate.toValue= [NSValuevalueWithCGPoint:CGPointMake(100,100)];

//缩放动画

CABasicAnimation*scale = [CABasicAnimationanimationWithKeyPath:@"transform.scale"];

scale.toValue=@0.5;//旋转动画

CABasicAnimation*rotation = [CABasicAnimationanimationWithKeyPath:@"transform.rotation"];

rotation.toValue=@(M_PI);//把以上动画添加到动画组中

CAAnimationGroup*animationGroup = [CAAnimationGroupanimation];

animationGroup.animations=@[translate,scale,rotation];

//设置动画的时间animationGroup.duration=2.0;//动画组是否移动动画属性 失效

//animationGroup.removedOnCompletion = NO;

animationGroup.repeatCount=MAXFLOAT;

animationGroup.autoreverses=YES;

7.8.转场动画CATransition

[self.myLayeraddAnimation:animationGroupforKey:nil];

}

//添加转场动画UIImageView会自动按照转场动画来加载下一张图片

CATransition*animation = [CATransitionanimation];

animation.duration=1;

animation.type=@"pageCurl";

animation.subtype=kCATransitionFromTop;

[self.imageView.layeraddAnimation:animationforKey:nil];

7.9.添加动画到CALayer对象addAniamtion:forKey:

7.10.避免重复添加动画1.addAniamtion:forKey:这里要给一个Key

2.判断当前layer是否已经添加了此动画animationForKey:

7.11. CALayer上动画的暂停

[self.imageView.layeraddAnimation:animationforKey:nil];

NSString *key =@"myPosition";if([self.redLayer animationForKey:key] !=nil)return;

#pragma mark暂停CALayer的动画-(void)pauseLayer:(CALayer*)layer

{

CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];

//让CALayer的时间停止走动layer.speed = 0.0;

//让CALayer的时间停留在pausedTime这个时刻

layer.timeOffset = pausedTime;

}

7.12. CALayer上动画的恢复

#pragma mark恢复CALayer的动画-(void)resumeLayer:(CALayer*)layer

{

CFTimeInterval pausedTime = layer.timeOffset;

// 1.让CALayer的时间继续行走

layer.speed = 1.0;

// 2.取消上次记录的停留时刻

layer.timeOffset = 0.0;

// 3.取消上次设置的时间layer.beginTime = 0.0;

// 4.计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime)

CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()

fromLayer:nil] - pausedTime;

// 5.设置相对于父坐标系的开始时间(往后退timeSincePause)

layer.beginTime = timeSincePause;

}

7.13.动画的其它设置

7.13.1. duration

动画时长

7.13.2. fillMode

填充模式

7.13.3. removeOnCompletion

动画完成后是否删除动画

7.13.4. repeatCount

重复次数

7.13.5. autoreverse

播放之后原路返回

7.13.6. delegate

动画代理

7.13.7. repeatDuration

重复时间

7.13.8. beginTime

可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

7.13.9. timingFunction

速度控制函数,控制动画运行的节奏

8. UIView封装的动画与核心动画区别8.1.UIView封装的动画

[UIViewanimateWithDuration:1.0animations:^{self.redView.transform=

CGAffineTransformTranslate(self.redView.transform,100,100);

}];

[UIViewtransitionWithView:self.viewduration:1.0options:UIViewAnimationOptionRepeat animations:^{

}completion:^(BOOLfinished) {

}];

8.2.UIView封装的动画与核心动画的区别核心动画一切都是假象。位置并没有发生改变。

UIView动画是位置发生了改变

9.定时器介绍

9.1.NSTimer

1.系统计时器。2.使用

[NSTimerscheduledTimerWithTimeInterval:1.0target:selfselector:@selector(timerun)userInfo:nilrepeats:YES];

- (void)timerun{NSLog(@"time run");

}

9.2.CADisplayLink

1.CADisplayLink是一种以屏幕刷新频率触发的时钟机制,每秒钟执行大约60次左右2.CADisplayLink是一个计时器,可以使绘图代码与视图的刷新频率保持同步,而NSTimer

无法确保计时器实际被触发的准确时间

3.使用方法:

定义CADisplayLink并制定触发调用方法

将显示链接添加到主运行循环队列

9.3.dispatch_after延迟

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,

(int64_t)(0.1* NSEC_PER_SEC)), dispatch_get_main_queue(),

^{});

10.转盘效果10.1.布局界面

1.自定义xib

2.按照UI给的背景图片布局-Image属性

10.2.核心动画旋转界面

CABasicAnimation*anim = [CABasicAnimationanimation];

anim.keyPath=@"transform.rotation";

anim.toValue=@(M_PI*2*3);

anim.duration=0.5;

anim.delegate=self;

[self.wheelViews.layeraddAnimation:animforKey:@"wheel"];

10.3. awakeFromNib添加按钮

for(inti =0;i <12;i++){WheelButton*button = [WheelButton

buttonWithType:UIButtonTypeCustom];

button.bounds=CGRectMake(0,0,68,143);

button.layer.position=self.center;

button.layer.anchorPoint=CGPointMake(0.5,1);

[self.wheelViewaddSubview:button];

}

10.4.旋转按钮CGAffineTransformRotate

#define angle2Arc(angle) (angle * M_PI /180)

button.transform=CGAffineTransformRotate(button.transform,angle2Arc(i *30) );

10.5.设置按钮选中时背景色

10.6.设置按钮点击事件—点击选中

[buttonsetBackgroundImage:[UIImageimageNamed:@"LuckyRototeSelected"]forState:UIControlStateSelected];

[buttonaddTarget:selfaction:@selector(btnClick:)forControlEvents:UIControlEventTouchDown];

- (void)btnClick:(UIButton*)btn{

btn.selected=YES;

}

10.7.取消上一个按钮选中

- (void)btnClick:(UIButton*)btn{self.selectedBtn.selected=NO;

btn.selected=YES;self.selectedBtn= btn;

}

#pragma mark --懒加载定时器

- (CADisplayLink*)link{if(_link==nil){

_link= [CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(updateView)];

[_linkaddToRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];

}

return_link;

}

#pragma mark --旋转界面

- (void)updateView{self.wheelView.transform=

CGAffineTransformRotate(self.wheelView.transform,angle2Arc(45/60.0));

}

- (void)startSlowRun{self.link.paused=NO;

}

- (void)stopSlowRun{

self.link.paused=YES;

}

10.9.添加按钮上正常状态的图片

UIImage*normalImage = [UIImageimageNamed:@"LuckyAstrology"];

CGFloatnormalW = normalImage.size.width/12;CGFloatnormalH = normalImage.size.height;

CGFloatscale = [UIScreenmainScreen].scale;if(scale >2) scale =2;

normalW = normalW * scale;

normalH = normalH * scale;

CGFloatnormalX = i * normalW;CGFloatnormalY =0;

CGImageRefnormalItemImage =CGImageCreateWithImageInRect(normalImage.CGImage,CGRectMake(normalX, normalY, normalW, normalH));

[buttonsetImage:[UIImageimageWithCGImage:normalItemImage]forState:UIControlStateNormal];

10.10.添加按钮上选中状态的图片

UIImage *selectedImage = [UIImage

imageNamed:@"LuckyAstrologyPressed"];

CGFloat selectedW = selectedImage.size.width /12;CGFloatselectedH = selectedImage.size.height;

selectedW = selectedW * scale;

selectedH = selectedH * scale;

CGFloatselectedX = i * selectedW;

CGFloatselectedY =0;

CGImageRefselectedItemImage =CGImageCreateWithImageInRect(selectedImage.CGImage,CGRectMake(selectedX, selectedY, selectedW, selectedH));

[buttonsetImage:[UIImageimageWithCGImage:selectedItemImage]forState:UIControlStateSelected];

10.11.自定义按钮—解决图片布局问题

- (CGRect)imageRectForContentRect:(CGRect)contentRect{CGFloatx = (contentRect.size.width-40) *0.5;

returnCGRectMake(x,20,40,47);

}

10.12.自定义按钮—去掉高亮

10.13.开始选号—核心动画

- (void)setHighlighted:(BOOL)highlighted{}

- (IBAction)startRun:(UIButton*)sender {

staticNSString*key =@"rotation";if([self.wheelView.layeranimationForKey:key])return;CABasicAnimation*animation = [CABasicAnimation

animationWithKeyPath:@"transform.rotation"];

animation.toValue=@(M_PI*2*3);

animation.duration=4;

animation.delegate=self;

[self.wheelView.layeraddAnimation:animation

forKey:key];

}

10.14.选号动画结束后停在选中按钮位置

- (void)animationDidStop:(CAAnimation*)anim

finished:(BOOL)flag{

CGFloatangle =atan2(self.selectedBtn.transform.b,self.selectedBtn.transform.a);

self.wheelView.transform=CGAffineTransformMakeRotation(-angle);

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容