您的位置:首页 > 其它

CoreAnimation

2015-01-13 14:19 489 查看
一、CALayer常用属性:

属性 说明 是否支持隐式动画 
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中很少使用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:

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);
}
@end
KCView.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息