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);
}