CoreAnimation
2015-01-13 14:19
489 查看
一、CALayer常用属性:
在CALayer中很少使用frame属性,因为frame本身不支持动画效果,通常使用bounds和position代替。
CALayer中透明度使用opacity表示而不是alpha;中心点使用position表示而不是center。
MasksToBounds=YES之后,阴影不起作用,可以在其下面再添加一层阴影图层,实现圆角加阴影效果。
CAAnimation和CALayer是键值编码适应的容器类,容器类的意思是你可以为任意的键设置值。即使有些键在CALayer中没有声明,你仍然可以像下面一样设置值:
[theLayer setValue:@50 forKey:@”someKey”];
你可以像检索其他键路径一样检索任意键的值。比如为了检索之前设置的someKey键的值,可以像下面代码一样操作:
someKeyValue = [theLayer valueForKey:@”someKey”];
二、在iOS中核心动画分为几类:基础动画、关键帧动画、动画组、转场动画。各个类的关系大致如下:
CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议。
CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用。
CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行。
CATransition:转场动画,主要通过滤镜进行动画效果设置。
CABasicAnimation:基础动画,通过属性修改进行动画参数控制,只有初始状态和结束状态。
CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制。
(1)、CABasicAnimation:
关于动画keyPath:
transform.scale =比例轉換
transform.scale.x =闊的比例轉換
transform.scale.y =高的比例轉換
transform.rotation.z =平面圖的旋轉
opacity =透明度
margin、zPosition、backgroundColor、cornerRadius、borderWidth、bounds、contents、contentsRect、cornerRadius、frame、hidden、mask、masksToBounds、opacity、position、shadowColor、shadowOffset、shadowOpacity、shadowRadius、
(2)、CAKeyframeAnimation:
关键帧分两种类型:
(3)、CAAnimationGroup:
(4)、CATransition:
另外对于支持方向设置的动画类型还包含子类型:
注:可以实现无限循环图片浏览器。
三、动画相关重点:
(1)、CATransaction :
CATransaction 事务类,可以对多个layer的属性同时进行修改.它分隐式事务,和显式事务.
区分隐式动画和隐式事务:隐式动画通过隐式事务实现动画 。
区分显式动画和显式事务:显式动画有多种实现方式,显式事务是一种实现显式动画的方式。
除显式事务外,任何对于CALayer属性的修改,都是隐式事务.这样的事务会在run-loop中被提交.
显示事务通过明确的调用begin,commit来提交动画
(2)、动画暂停与继续:
KCALayer.m文件
(5)、给CALayer添加图片:
drawInContext
属性 | 说明 | 是否支持隐式动画 |
---|---|---|
anchorPoint | 和中心点position重合的一个点,称为“锚点”,锚点的描述是相对于x、y位置比例而言的默认在图像中心点(0.5,0.5)的位置 | 是 |
backgroundColor | 图层背景颜色 | 是 |
borderColor | 边框颜色 | 是 |
borderWidth | 边框宽度 | 是 |
bounds | 图层大小 | 是 |
contents | 图层显示内容,例如可以将图片作为图层内容显示 | 是 |
contentsRect | 图层显示内容的大小和位置 | 是 |
cornerRadius | 圆角半径 | 是 |
doubleSided | 图层背面是否显示,默认为YES | 否 |
frame | 图层大小和位置,不支持隐式动画,所以CALayer中很少使用frame,通常使用bounds和position代替 | 否 |
hidden | 是否隐藏 | 是 |
mask | 图层蒙版 | 是 |
maskToBounds | 子图层是否剪切图层边界,默认为NO | 是 |
opacity | 透明度 ,类似于UIView的alpha | 是 |
position | 图层中心点位置,类似于UIView的center | 是 |
shadowColor | 阴影颜色 | 是 |
shadowOffset | 阴影偏移量 | 是 |
shadowOpacity | 阴影透明度,注意默认为0,如果设置阴影必须设置此属性 | 是 |
shadowPath | 阴影的形状 | 是 |
shadowRadius | 阴影模糊半径 | 是 |
sublayers | 子图层 | 是 |
sublayerTransform | 子图层形变 | 是 |
transform | 图层形变 | 是 |
CALayer中透明度使用opacity表示而不是alpha;中心点使用position表示而不是center。
MasksToBounds=YES之后,阴影不起作用,可以在其下面再添加一层阴影图层,实现圆角加阴影效果。
CAAnimation和CALayer是键值编码适应的容器类,容器类的意思是你可以为任意的键设置值。即使有些键在CALayer中没有声明,你仍然可以像下面一样设置值:
[theLayer setValue:@50 forKey:@”someKey”];
你可以像检索其他键路径一样检索任意键的值。比如为了检索之前设置的someKey键的值,可以像下面代码一样操作:
someKeyValue = [theLayer valueForKey:@”someKey”];
二、在iOS中核心动画分为几类:基础动画、关键帧动画、动画组、转场动画。各个类的关系大致如下:
CAAnimation:核心动画的基础类,不能直接使用,负责动画运行时间、速度的控制,本身实现了CAMediaTiming协议。
CAPropertyAnimation:属性动画的基类(通过属性进行动画设置,注意是可动画属性),不能直接使用。
CAAnimationGroup:动画组,动画组是一种组合模式设计,可以通过动画组来进行所有动画行为的统一控制,组中所有动画效果可以并发执行。
CATransition:转场动画,主要通过滤镜进行动画效果设置。
CABasicAnimation:基础动画,通过属性修改进行动画参数控制,只有初始状态和结束状态。
CAKeyframeAnimation:关键帧动画,同样是通过属性进行动画参数控制,但是同基础动画不同的是它可以有多个状态控制。
(1)、CABasicAnimation:
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"position"]; basicAnimation.delegate=self; [basicAnimation setValue:[NSValue valueWithCGPoint:location] forKey:@"endLocation"]; //支持键值编码 basicAnimation.fromValue=[NSValue valueWithCGPoint:_layer.position]; basicAnimation.toValue=[NSValue valueWithCGPoint:location]; basicAnimation.duration=.3; // basicAnimation.removedOnCompletion=FALSE; // basicAnimation.fillMode=kCAFillModeBoth; // fillMode的作用就是决定当前对象过了非active时间段的行为. 比如动画开始之前,动画结束之后。如果是一个动画CAAnimation,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用. // kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态 // kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态 // kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始.你可以这样设定测试代码,将一个动画加入一个layer的时候延迟5秒执行.然后就会发现在动画没有开始的时候,只要动画被加入了layer,layer便处于动画初始状态 // kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态. [_layer addAnimation:basicAnimation forKey:@"positionAnimation"];
关于动画keyPath:
transform.scale =比例轉換
transform.scale.x =闊的比例轉換
transform.scale.y =高的比例轉換
transform.rotation.z =平面圖的旋轉
opacity =透明度
margin、zPosition、backgroundColor、cornerRadius、borderWidth、bounds、contents、contentsRect、cornerRadius、frame、hidden、mask、masksToBounds、opacity、position、shadowColor、shadowOffset、shadowOpacity、shadowRadius、
(2)、CAKeyframeAnimation:
关键帧分两种类型:
//第一种方式:关键值 CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; NSArray *values=@[[NSValue valueWithCGPoint:_layer.position], [NSValue valueWithCGPoint:CGPointMake(150, 140)], [NSValue valueWithCGPoint:CGPointMake(120, 160)], [NSValue valueWithCGPoint:CGPointMake(150, 200)], [NSValue valueWithCGPoint:location]]; keyframeAnimation.values=values; NSArray *times=@[[NSNumber numberWithFloat:.0], [NSNumber numberWithFloat:.3], [NSNumber numberWithFloat:.6], [NSNumber numberWithFloat:.8], [NSNumber numberWithFloat:1.0]]; keyframeAnimation.keyTimes=times; keyframeAnimation.duration=4.0; [_layer addAnimation:keyframeAnimation forKey:@"keyAnimation"];</span>
//第二种方式:关键路径 CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; CGMutablePathRef pathRef = CGPathCreateMutable(); CGPathMoveToPoint(pathRef, NULL, _layer.position.x, _layer.position.y); CGPathAddCurveToPoint(pathRef, NULL, 100, 300, 250, 300, 175, 480); keyframeAnimation.path=pathRef; NSArray *times=@[[NSNumber numberWithFloat:.0], [NSNumber numberWithFloat:.3], [NSNumber numberWithFloat:.6], [NSNumber numberWithFloat:.8], [NSNumber numberWithFloat:1.0]]; keyframeAnimation.keyTimes=times; keyframeAnimation.duration=4.0; keyframeAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; /** Timing function names. **/ /* CA_EXTERN NSString * const kCAMediaTimingFunctionLinear //直线匀速 __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseIn //减速 __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseOut //加速 __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseInEaseOut //先减速再加速 __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAMediaTimingFunctionDefault //默认 __OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0); */ // keyframeAnimation.calculationMode=kCAAnimationDiscrete; /* CA_EXTERN NSString * const kCAAnimationLinear __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAAnimationDiscrete __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAAnimationPaced __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0); CA_EXTERN NSString * const kCAAnimationCubic __OSX_AVAILABLE_STARTING (__MAC_10_7, __IPHONE_4_0); CA_EXTERN NSString * const kCAAnimationCubicPaced __OSX_AVAILABLE_STARTING (__MAC_10_7, __IPHONE_4_0); */ [_layer addAnimation:keyframeAnimation forKey:@"keyAnimation"];
(3)、CAAnimationGroup:
- (CABasicAnimation *)scaleAnimaion { CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.scale"]; basicAnimation.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeScale(transformScale, transformScale, 1)]; return basicAnimation; } - (CABasicAnimation *)rotationAnimation { CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; basicAnimation.toValue=[NSNumber numberWithFloat:M_PI_2*3]; return basicAnimation; } - (void)groupAnimation { CABasicAnimation *scaleAnimation=[self scaleAnimaion]; CABasicAnimation *rotationAnimation=[self rotationAnimation]; CAAnimationGroup *groupAnimation=[CAAnimationGroup animation]; groupAnimation.animations=@[scaleAnimation,rotationAnimation]; groupAnimation.duration=animationTime; groupAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; groupAnimation.autoreverses=true; groupAnimation.repeatCount=HUGE_VALF; [_layer addAnimation:groupAnimation forKey:@"groupAnimation"]; _start=YES; }
(4)、CATransition:
CATransition *transition =[[CATransition alloc]init]; transition.type=kCATransitionMoveIn; //对于苹果官方没有公开的动画类型,只能用字符串来表示,并没有常量定义。// transition.type=@"cube"; transition.type=kCATransitionMoveIn ; transition.subtype=kCATransitionFromRight; [_imgView.layer addAnimation:transition forKey:@"Transition"];
动画类型 | 说明 | 对应常量 | 是否支持方向设置 |
---|---|---|---|
公开API | |||
fade | 淡出效果 | kCATransitionFade | 是 |
movein | 新视图移动到旧视图上 | kCATransitionMoveIn | 是 |
push | 新视图推出旧视图 | kCATransitionPush | 是 |
reveal | 移开旧视图显示新视图 | kCATransitionReveal | 是 |
私有API | 私有API只能通过字符串访问 | ||
cube | 立方体翻转效果 | 无 | 是 |
oglFlip | 翻转效果 | 无 | 是 |
suckEffect | 收缩效果 | 无 | 否 |
rippleEffect | 水滴波纹效果 | 无 | 否 |
pageCurl | 向上翻页效果 | 无 | 是 |
pageUnCurl | 向下翻页效果 | 无 | 是 |
cameralIrisHollowOpen | 摄像头打开效果 | 无 | 否 |
cameraIrisHollowClose | 摄像头关闭效果 | 无 | 否 |
动画子类型 | 说明 |
---|---|
kCATransitionFromRight | 从右侧转场 |
kCATransitionFromLeft | 从左侧转场 |
kCATransitionFromTop | 从顶部转场 |
kCATransitionFromBottom | 从底部转场 |
三、动画相关重点:
(1)、CATransaction :
CATransaction 事务类,可以对多个layer的属性同时进行修改.它分隐式事务,和显式事务.
区分隐式动画和隐式事务:隐式动画通过隐式事务实现动画 。
区分显式动画和显式事务:显式动画有多种实现方式,显式事务是一种实现显式动画的方式。
除显式事务外,任何对于CALayer属性的修改,都是隐式事务.这样的事务会在run-loop中被提交.
//设置变化动画过程是否显示,默认为YES不显示 [CATransaction setDisableActions:NO]; //设置圆角 layer.cornerRadius = (layer.cornerRadius == 0.0f) ? 30.0f : 0.0f; //设置透明度 layer.opacity = (layer.opacity == 1.0f) ? 0.5f : 1.0f;
显示事务通过明确的调用begin,commit来提交动画
[CATransaction begin]; [CATransaction begin]; [CATransaction setDisableActions:YES]; layer.cornerRadius = (layer.cornerRadius == 0.0f) ? 30.0f : 0.0f; [CATransaction commit]; //上面的动画并不会立即执行,需要等最外层的commit [NSThread sleepForTimeInterval:10]; //显式事务默认开启动画效果,kCFBooleanTrue关闭 [CATransaction setValue:(id)kCFBooleanFalse forKey:kCATransactionDisableActions]; //动画执行时间 [CATransaction setValue:[NSNumber numberWithFloat:10.0f] forKey:kCATransactionAnimationDuration]; //[CATransaction setAnimationDuration:[NSNumber numberWithFloat:5.0f]]; anotherLayer.cornerRadius = (anotherLayer.cornerRadius == 0.0f) ? 30.0f : 0.0f; [CATransaction commit];
(2)、动画暂停与继续:
- (IBAction)continueAnimation:(id)sender { if (_layer.speed==0) { CFTimeInterval beginTime=CACurrentMediaTime()-_layer.timeOffset; _layer.timeOffset=0; _layer.beginTime=beginTime; _layer.speed=1; } } - (IBAction)pauseAnimation:(id)sender { if (_layer.speed==1) { _layer.timeOffset=[_layer convertTime:CACurrentMediaTime() fromLayer:nil]; _layer.speed=0; } }(3)、动画定时器:
- (void)viewDidLoad { [super viewDidLoad]; _index=0; CADisplayLink *displayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(bgColorChange:)]; [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // Do any additional setup after loading the view. } -(void)bgColorChange:(CADisplayLink *)displayLink { _index++; if (_index==400) { [displayLink invalidate]; } int value_r=arc4random()%255; int value_g=arc4random()%255; int value_b=arc4random()%255; self.view.backgroundColor=[UIColor colorWithRed:value_r/255.0 green:value_g/255.0 blue:value_b/255.0 alpha:1]; }(4)、drawRect:与drawLayer:inContext、drawInContext:
KCALayer.m文件
#import "KCALayer.h" @implementation KCALayer - (void)drawInContext:(CGContextRef)ctx { NSLog(@"3-drawInContext:"); NSLog(@"CGContext:%@",ctx); } @endKCView.m文件
#import "KCView.h" #import "KCALayer.h" @implementation KCView - (instancetype)initWithFrame:(CGRect)frame { if (self=[super initWithFrame:frame]) { KCALayer *layer=[[KCALayer alloc]init]; layer.bounds=CGRectMake(0, 0, 185, 185); layer.position=CGPointMake(160, 284); layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor; [layer setNeedsDisplay]; [self.layer addSublayer:layer]; } return self; } -(void)drawRect:(CGRect)rect{ NSLog(@"2-drawRect:"); NSLog(@"CGContext:%@",UIGraphicsGetCurrentContext());//得到的当前图形上下文正是drawLayer中传递的 [super drawRect:rect]; } -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ NSLog(@"1-drawLayer:inContext:"); NSLog(@"CGContext:%@",ctx);[super drawLayer:layer inContext:ctx]; @end
(5)、给CALayer添加图片:
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{ // NSLog(@"%@",layer);//这个图层正是上面定义的图层 UIImage *image=[UIImage imageNamed:@"touxiang.jpg"]; //注意这个位置是相对于图层而言的不是屏幕 CGContextDrawImage(ctx, CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT), image.CGImage); }
layer.contents = (id)[UIImage imageNamed:@"view_BG.png"].CGImage; // 给图层添加背景图片
drawInContext
相关文章推荐
- 核心动画 CoreAnimation
- iOS动画—UIView动画以及CoreAnimation动画
- CoreAnimation的介绍
- 使用Instruments中的CoreAnimation分析动画
- [IOS]CoreAnimation基础[翻译4部分]
- CoreAnimation-09-模拟时钟
- iOS CoreAnimation系列教程
- iOS动画和特效(一)UIView动画和CoreAnimation
- CoreAnimation 和 CoreGraphics
- CoreAnimation
- 一、CoreAnimation之图层树详解
- CoreAnimation —— Layer
- CoreAnimation 视觉效果
- iOS 动画篇 (二) CAShapeLayer与CoreAnimation结合使用
- 使用CoreAnimation实现最简单的拖拽转盘效果
- Core Animation学习笔记 核心动画 CoreAnimation
- CoreAnimation注意事项
- ios(CoreAnimation核心动画 一) CABasicAnimation动画与锚点
- [IOS]CoreAnimation基础[翻译5部分]
- iOS高级-QuartzCore框架-CoreAnimation和UIView动画的使用