CoreAnimation

一、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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值