ios 动画基础(一)

每个UIView都有关联的CALayer对象,被称之为rootLayer。

隐式动画

隐式动画指我们没有指定任何动画类型,只是改变了layer的属性,有框架自动完成动画效果,默认持续时间是0.25s;但是只有非rootLayer(自己创建的)才有隐式动画,具体原因如下:

我们把改变属性时CALayer自动应用的动画称作action,当CALayer的属性被修改时候,它会调用actionForKey:方法,传递属性的名称。具体见如下步骤:

  • 图层首先检测它是否有委托,并且是否实现CALayerDelegate协议指定的actionForLayer:forKey方法。如果有,直接调用并返回结果。
  • 如果没有委托,或者委托没有实现-actionForLayer:forKey方法,图层接着检查包含属性名称对应行为映射的actions字典。
  • 如果actions字典没有包含对应的属性,那么图层接着在它的style字典接着搜索属性名。
  • 最后,如果在style里面也找不到对应的行为,那么图层将会直接调用定义了每个属性的标准行为的-defaultActionForKey:方法。
    在一轮完整的搜索结束之后,-actionForKey:要么返回空(这种情况下将不会有动画发生),要么返回CAAction协议的对象,最后CALayer拿这个结果去做动画。

每个UIView对它关联的图层都扮演了一个委托,并且提供了-actionForLayer:forKey的实现方法。当不在一个动画块的实现中,UIView对所有图层行为返回nil,但是在动画block范围之内,它就返回了一个非空值。

 NSLog(@"Outside: %@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
 //begin animation block
 [UIView beginAnimations:nil context:nil];
 //test layer action when inside of animation block
 NSLog(@"Inside: %@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
 //end animation block
 [UIView commitAnimations];

打印结果如下
Outside:
Inside:

具体可见官方文档
在objc中View-Layer 协作也有说明

  1. Layer可动画属性 ,如
  • bounds:用于设置CALayer的宽度和高度,修改这个属性会产生缩放动画;
  • backgroundColor:用于设置CALayer的背景色,修改这个属性会产生背景色的渐变动画;
  • position:用于设置CALayer的位置,修改这个属性会产生平移动画等等,可以在CALayer的头文件中看到
  1. 利用CATransaction来改变默认的隐式动画
    CATransaction说明
    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0];
    self.colorLayer.backgroundColor = [[UIColor yellowColor] CGColor];
    [CATransaction commit];

显式动画

  1. 属性动画:作用于图层的某个单一属性,并指定了它的一个目标值,或者一连串将要做动画的值。
  2. 动画组:将多个属性动画组合到一起。
  3. 动画过渡:不像属性动画那样平滑地在两个值之间做动画,而是影响到整个图层的变化;过渡动画首先展示之前的图层样子,然后过渡到新的样子。


    ios 动画基础(一)_第1张图片
    core animation结构

    先来介绍属性动画下基础动画

CABasicAnimation

1.先看一个实现平移动画的

    CALayer *layer = [[CALayer alloc]init];
    layer.backgroundColor = [[UIColor grayColor]CGColor];
    layer.frame = CGRectMake(40, 20, 40, 40);
    layer.cornerRadius = 5;
    [self.view.layer addSublayer:layer];
    //平移动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.duration = 3.0;
    animation.autoreverses = YES;
    animation.repeatCount = HUGE_VALF;
    animation.fromValue = [NSValue valueWithCGPoint:layer.position];
    CGPoint toPoint = layer.position;
    toPoint.x = toPoint.x+180;
    animation.toValue = [NSValue valueWithCGPoint:toPoint];
    [layer addAnimation:animation forKey:@"move"];

先是新建了一个layer,然后利用keyPath创建了一个动画,通过设置属性定义动画效果,最后将动画添加到layer上。
keyPath的值,这边列出比较常用,还有一些和上面叙述的layer的属性类似

keyPath的值 说明
position 位置变化,引起平移动画
transform.scale 比例变化,放大缩小
transform.scale.x 宽度缩放
transform.scale.y 高度缩放
transform.rotation 旋转
transform.rotation.x 沿x轴旋转
transform.rotation.y 沿y轴旋转
transform.rotation.z 沿z轴旋转
opacity 透明度
backgroundColor 背景颜色
cornerRadius 圆角

animation的属性

属性 说明
fromValue 动画改变的属性初始值
toValue 动画改变的属性结束值
byValue 过程中属性相对初始值改变的值
duration 动画持续时长
repeatCount 动画重复次数,不停重复设置为 HUGE_VALF
repeatDuration 动画应该被重复多久,动画会一直重复,直到设定的时间流逝完;它不应该和 repeatCount 一起使用。
autoreverses 动画结束时是否执行逆动画,当你设定这个属性为 YES 时,在它到达目的地之后,动画的返回到开始的值,代替了直接跳转到 开始的值。
beginTime 指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式
timingFunction 设置动画的速度变化,这个略复杂,稍候介绍

2.如果要定义动画开始之前或结束之后的状态,可以用fillMode;不过要注意要在CABasicAnimation 中fillMode启作用,需要将removedOnCompletion设为NO,具体见CABasicAnimation fillMode和removedOnCompletion

scaleAnimation.removedOnCompletion = NO;
scaleAnimation.fillMode = kCAFillModeForwards;

解释:为什么动画结束后返回原状态?
layer有两个重要属性modelLayer和presentationLayer(还有一个renderingLayer,是私有的);modelLayer表现了我们看到的layer状态,当改变layer的属性值,modelLayer的属性值也即刻改变;presentationLayer则表现的是动画过程中状态值。
而当我们给一个layer添加动画时,动画开始时 presentation layer在不断变化,动画结束时,presentation layer从屏幕上移除,原始layer显示。如果没有改变过modelLayer的值,那么在动画结束之后就会返回到原状态。

3.其他例子

    //旋转动画
    CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
    rotateAnimation.duration = 3.0;
    rotateAnimation.repeatCount = HUGE_VALF;
    rotateAnimation.autoreverses = YES;
    rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
    rotateAnimation.toValue = [NSNumber numberWithFloat:6*M_PI];
    [rotateLayer addAnimation:rotateAnimation forKey:@"rotate"];
    //....
    //放大、缩小
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];
    scaleAnimation.duration = 3.0;
    scaleAnimation.repeatCount = HUGE_VALF;
    scaleAnimation.autoreverses = YES;
    scaleAnimation.removedOnCompletion = NO;
    scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
    scaleAnimation.toValue = [NSNumber numberWithFloat:2.5];
    scaleAnimation.fillMode = kCAFillModeForwards;
    [scaleLayer addAnimation:scaleAnimation forKey:@"scale"];

参考资料

core animation官方文档
浅谈animation
CABasicAnimation使用总结
显式动画
隐式动画
让你的动画动起来

你可能感兴趣的:(ios 动画基础(一))