核心动画(CoreAnimation)作为苹果官方基于OpenGLES封装的一套动画框架。使用起来相对于OpenGLES简单的多。也更容易被绝大多数OC开发者使用。
先来看一下相关框架图
![](https://img.haomeiwen.com/i3028784/e048c799b7599aed.png)
日常中,我们基于UIView的layer做动画要多一些。我们先看一下CALayer。
CALayer.
为什么叫CALayer?CoreAnimationLayer。在命名里就能看得出来,CALayer的核心作用就是来处理动画。
UIView与CALayer的关系
首先,UIView是CALayer的delegate。
其次,UIView与CALayer承载不同的功能,两者的分工自然应该是明确的(职责分离)。
最后,CALayer不清楚响应链关系,所以CALayer无法用来处理交互事件。而UIView继承自UIResponser,所以由UIView处理事件交互。而UIView作为CALayer的代理,自然也可以实现一些简单的CALayer的方法。但要实现稍微复杂些的动画效果,就需要借助CALayer,如:
- 阴影,圆角,带颜色的边框
- 3D变换
- 非矩形范围
- 透明遮罩
- 多级非线性动画
对于layer的树级关系:
- 模型树( layer tree):程序中接触最频繁。模型树的对象是模型对象,储存着动画的目标值。当你修改layer的属性时,便是通过模型树上的对象。
- 呈现树(presentation tree):包含正在运行中的动画的动态值。与模型树不同,呈现树始终存储着layer在屏幕当前的状态值。呈现树无法修改,只读。可以通过读取当前值,来做一些其他处理。
- 渲染树(render tree):执行实际的动画,为Core Animation私有。
![](https://img.haomeiwen.com/i3028784/374ced425b0542bc.png)
接下来我们来做一个简单的动画:
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(100, 100, 100, 100);
layer.backgroundColor = [UIColor orangeColor].CGColor;
_layer = layer;
[self.view.layer addSublayer:layer];
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.y";
animation.toValue = @400;
animation.duration = 1;
[_layer addAnimation:animation forKey:nil];
}
我们会发现动画执行完毕后,又回到了初始位置。为什么会这样?
还记得上面中我们提到过layerTree跟presentationTree吧。其实在执行动画的时候会有两个图层,一个是layer层,一个是presentation层。当动画开始前,会先把layer层隐藏,让presentation层做动画。动画做完后,presentation层移除,layer层出现。所以其实我们的视图的layer层根本没有发生变化。怎么解决呢?
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.y";
animation.toValue = @400;
animation.duration = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[_layer addAnimation:animation forKey:nil];
}
我们仅仅多加了两行代码:
第一行代码的意思是:当动画完成后,不把presentation层从render树中移除(默认是移除的)。
第二行代码的意思是:当动画结束后,layer层会把状态同步到presentation层。
如果想做连续动画
一:可以设置一下代理
animation.delegate = self;
在下面这个方法里,监听动画完成,然后执行下一个动画。
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
不过这里有两个坑点:
坑点一:这个delegate默认把动画对象retain了一份。所以你的animation对象跟代理方法里的anim不是同一个对象
坑点二:这个delegate是个strong类型,动画执行完毕后,需要额外处理一下才能把代理释放。这里有两个方式:
方式一:在动画完成的代理里,把所有的动画全部移除。
方式二:继承CABasicAnimation后,重写代理方法。
另外CAAnimation默认是有隐式动画的,动画时间为0.25s。可以通过CATransaction设置隐式动画的时间。代码如下:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CABasicAnimation *animation = [CABasicAnimation animation];
_animation = animation;
animation.keyPath = @"position.y";
animation.toValue = @400;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[CATransaction begin];
[CATransaction setAnimationDuration:10];
[_layer addAnimation:animation forKey:nil];
[CATransaction commit];
}
二:通过动画组来实现
CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
animation1.fromValue = @(1.0);
animation1.toValue = @(1.5);
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];
animation2.fromValue = @(1.0);
animation2.toValue = @(1.5);
CABasicAnimation *animation3 = [CABasicAnimation animationWithKeyPath:@"position"];
animation3.fromValue = [NSValue valueWithCGPoint:_ballLayer.position];
animation3.toValue = [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width - (30 * 1.3)/2.0 , _ballLayer.position.y - 200)];
CAAnimationGroup *anima = [CAAnimationGroup animation];
anima.animations = @[animation1, animation2,animation3];
anima.duration = 1.0;
anima.delegate = (id)self;
anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
anima.fillMode = kCAFillModeForwards;
anima.removedOnCompletion = NO;
[_ballLayer addAnimation:anima forKey:@"group_launch"];
}
额外补充两点:
一、什么是hitTest
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
point : 在接收器的局部坐标系中指定的点。
event : 系统保证调用此方法的事件。如果从事件处理代码外部调用此方法,则可以指定nil。
returnValue : 视图对象是当前视图和包含点的最远的后代。如果点完全位于接收方的视图层次结构之外,则返回nil。
二:传递机制如下:
![](https://img.haomeiwen.com/i3028784/e0dd5803a10b92d2.png)
对于更多的动画效果可参考:https://www.jianshu.com/p/94f047efee6d
网友评论