每个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 协作也有说明
- Layer可动画属性 ,如
- bounds:用于设置CALayer的宽度和高度,修改这个属性会产生缩放动画;
- backgroundColor:用于设置CALayer的背景色,修改这个属性会产生背景色的渐变动画;
- position:用于设置CALayer的位置,修改这个属性会产生平移动画等等,可以在CALayer的头文件中看到
- 利用CATransaction来改变默认的隐式动画
CATransaction
说明
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
self.colorLayer.backgroundColor = [[UIColor yellowColor] CGColor];
[CATransaction commit];
显式动画
- 属性动画:作用于图层的某个单一属性,并指定了它的一个目标值,或者一连串将要做动画的值。
- 动画组:将多个属性动画组合到一起。
-
动画过渡:不像属性动画那样平滑地在两个值之间做动画,而是影响到整个图层的变化;过渡动画首先展示之前的图层样子,然后过渡到新的样子。
先来介绍属性动画下基础动画
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使用总结
显式动画
隐式动画
让你的动画动起来