Core Animation 学习笔记(二)
1.专用图层(Specialized Layers)
常用的图层大概有下面这几个:
CAShapeLayer
CATextLayer
CATransformLayer
CAGradientLayer
CAReplicatorLayer
CAScrollLayer
CATiledLayer
CAEmitterLayer
CAEAGLLayer
AVPlayerLayer
目前我只用过其中的几个,就简单讲讲自己用过的吧!
(1)CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图形,最后CAShapeLayer就会自动渲染出来。通常使用CAShapeLayer结合UIBezierPath绘制简单图形。用CAShapeLayer可以为每个角指定是否圆角。
下面这段代码绘制了一个有三个圆角一个直角的矩形:
// 定义路径参数
CGRect rect = CGRectMake(50, 50, 100, 100);
CGSize radii = CGSizeMake(20, 20);
UIRectCorner corners = UIRectCornerTopRight | UIRectCornerBottomRight | UIRectCornerBottomLeft;
// 创建路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];
(2)CAGradientLayer是用来生成两种或更多颜色平滑渐变的。用Core Graphics复制一个CAGradientLayer并将内容绘制到一个普通图层的寄宿图也可以实现这个效果,但是CAGradientLayer的真正好处在于绘制使用了硬件加速。使用CAGradientLayer不仅可以实现基础渐变(一种颜色渐变到另一种颜色),还能实现多重渐变(一种颜色渐变到多种颜色)。下面是一段多种渐变的例子:
- (void)viewDidLoad {
[super viewDidLoad];
// 创建梯度图层并添加到容器视图上
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.containerView.bounds;
[self.containerView.layer addSublayer:gradientLayer];
// 设置梯度颜色
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id [UIColor yellowColor].CGColor, (__bridge id)[UIColor greenColor].CGColor];
// 设置位置
gradientLayer.locations = @[@0.0, @0.25, @0.5];
// 设置梯度开始和结束点
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
}
(3)CAReplicatorLayer可以高效生成许多相似的图层。它会绘制一个或多个图层的子图层,并在每个 复制体上应用不同的变换。变换是逐步增加的,每个实例都是相 对于前一实例布局。这就是为什么这些复制体最终不会出现在同意位置上.使用CAReplicatorLayer和CAGradientLayer可以实现倒影的效果。
2.隐式动画(Implicit Animations)
当改变CALayer那个是否可以做动画的属性时,并不能立刻在屏幕上体现出来。相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作。例如改变图层颜色
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
这其实就是所谓的隐式动画。之所以叫内联是因为我们并没有指定任何动画的类型。改变了一个属性,然后Core Animation来决定如何并且何时去做动画。
(1)事务
事务指的是Core Animation用来包含一系列属性动画集合的机制,任何用指定事务去改变做动画的图层,属性都不会立刻发生变化,而是当事务一旦提交的时候开始用一个动画过渡到新值。使用CATransaction控制动画时间
- (IBAction)changeColor
{
// 开始一个新的事务
[CATransaction begin];
// 设置1秒的动画
[CATransaction setAnimationDuration:1.0];
// 随机给背景配色
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
// 提交事务
[CATransaction commit];
}
注意:UIView关联的图层禁用了隐式动画,对这种图层做动画的唯一办法就是使用UIView的动画函数。
3.显示动画(Implicit Animations)
(1)属性动画
动画其实就是一段时间内发生的改变,最简单的形式就是从一个值改变到另一个值,这也是CABasicAnimation最主要的功能。
- (IBAction)changeColor
{
// 创建一个新的随机颜色
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
// 创建一个基本动画
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"backgroundColor";
animation.toValue = (__bridge id)color.CGColor;
// 在图层上设置动画
[self.colorLayer addAnimation:animation forKey:nil];
}
运行程序,结果有点差强人意,点击按钮,的确可以使图层动画过渡到一个新的颜色,然动画结束之后又立刻变回原始值。
这是因为动画并没有改变图层的模型,而只是展现。一旦动画结束并从图层上移除之后,图层就立刻恢复到之前定义的外观状态。我们从没改变过backgroundColor属性,所以图层就返回到原始的颜色。
(2)CAKeyframeAnimation是另一种UIKit没有暴露但功能强大的类。CAKeyframeAnimation提供了关键节点的帧,然后Core Animation在非关键位置对每帧之间进行自动处理
(3)CAAnimationGroup可以把这些动画组合在一起形成一个动画组。
(4)过渡(CATransition)
属性动画只对图层的可动画属性起作用,所以如果要改变一个不能动画的属性(比如图片),或者从层级关系中添加或者移除图层,属性动画将不起作用。于是就有了过渡。过渡并不像属性动画那样平滑地在两个值之间做动画,而是影响到整个图层的变化。过渡动画首先展示之前的图层外观,然后通过一个交换过渡到新的外观。CATransition只提供了四种默认动画类型,太少了。但是苹果通过UIView +transitionFromView:toView:duration:options:completion:和+transitionWithView:duration:options:animations:方法提供了Core Animation的过渡特性。UIView过渡方法中options参数可以由如下常量指定:
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
UIViewAnimationOptionTransitionCrossDissolve
UIViewAnimationOptionTransitionFlipFromTop
UIViewAnimationOptionTransitionFlipFromBotto
小例子:用renderInContext:创建自定义过渡效果
@implementation ViewController
- (IBAction)performTransition
{
// 截图
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *coverImage = UIGraphicsGetImageFromCurrentImageContext();
// 插入截图
UIView *coverView = [[UIImageView alloc] initWithImage:coverImage];
coverView.frame = self.view.bounds;
[self.view addSubview:coverView];
// 更新视图(设置一个随机的背景色)
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
// 做自定义动画
[UIView animateWithDuration:1.0 animations:^{
// 放缩旋转和淡入淡出
CGAffineTransform transform = CGAffineTransformMakeScale(0.01, 0.01);
transform = CGAffineTransformRotate(transform, M_PI_2);
coverView.transform = transform;
coverView.alpha = 0.0;
} completion:^(BOOL finished) {
// 动画结束移除覆盖层
[coverView removeFromSuperview];
}];
}
@end
最后附上我看过的一本关于Core Animation的书籍《Core Animation Advanced Technology》,还要感谢“代码萝卜”的博客Core Animation Advanced Technique 学习笔记 - 代码萝卜