原文https://www.invasivecode.com/weblog/core-animation-part-ii-layers-everywhere/
我希望你们喜欢上一篇关于视图动画的文章,正如我享受着Eva的这篇文章(https://www.invasivecode.com/weblog/core-text)——核心文本,我们将结合核心动画和核心文本,就为了好玩!我也希望你们有机会玩转一些和之前的文章中给出的UIview类中提供的不同的方法。
我告诉你这类动画有什么限制:你不能同时在不等长的时间段里改变不同的视图属性。这意味着你不能,举个栗子啊J,你不能移动视图3秒的同时旋转它5秒。为了实现更复杂的动画并使它们完美的同步,你真的不能使用视图动画。但是再此强调一下,这类动画的主要优点是,它是像传言中一样很容易实现的,我相信就因为这个你会经常用它。
为了创建更复杂的动画,我们需要去CA框架里挖掘一些其他类。CA框架一开始是用于iPhone的,后来被移植到mac上。然而不管咋样,对你而言就是你有了一个简单灵活的方式去撸一些复杂的动画出来。
在iOS里,动画中的基本元素就是层(layer)。层是CALayer类的一个实例,它是MVC设计模式概念里充当M的那个模型类。如果你不知道我在说啥,额….你去面壁思过吧。去苹果的官方文档中找找模型视图控制器或者MVC设计模式。在特定情况下,一个CALayer对象包含一些你可以设置动画的属性值(位置,范围,背景颜色。边框宽度等)。最后的绘制,由包含这个layer的UIView来执行。这也意味着,CALayer直视一个数据容器,它没有显示,但是它代表着你要搞出动画的视图的属性值。
好了,其实并不是每个视图属性都可以被置于动画中,你可以在苹果官方文档的CA框架编程指南最后一章找到一个记录可动画属性的列表。要知道并不是他们所有属性都可以用于iOS。
正如Core Image在iOS里不能用,属性混合过滤器等在iOS2.0后可以用,但这些都没关系。
所有动画属性如下:(不翻译了,毕竟在xcode中编程也不会敲中文)anchorPoint, backgroundColor, borderColor, borderWidth, bounds, contents, contentRect, cornerRadius, doubleSided, frame, hidden, mask, masksToBounds, opacity, position, shadowColor, shadowOffset, shadowOpacity, shadowRadius, sublayers, sublayerTransform, transform 和 zPosition
苹果创造了一系列CALayer的特殊子类用来帮你做不同的任务。CATextLayer, CAScrollLayer, CAReplicatorLayer, CAShapeLayer, CAGradientLayer, CATiledLayer, CAOpenGLLayer 和 CAEAGLLayer是被定义在iOS中的子类,Mac OS X有一些其他的子类,我认为尽快把这些也移植到iOS中对苹果来说是有意义的。
去创建一个layer你有两种可能的方法。最简单的方法是让你准备移动的视图给你一个他自己的layer以供参考。每个视图都有它自己的layer。因此你可以这样做:
Objective-C:
CALayer *layer = [myView layer];
另外一个可能的方法就是你先创建一个layer,然后把它传给视图:
Objective-C:
CALayer *layer = [[CALayer alloc] init];
[myView setLayer:layer];
[layer release];
或者你可以这样用这个方便的方法+layer
Objective-C:
CALayer *layer = [CALayer layer];
[myView setLayer:layer];
所以,层包含描述层的那些属性,那么你怎么让它动起来呢?很简单,创建一个动画,然后加到该层。一旦你这样做,动画就开始了。你用-animation:forKeyPath:
方法来创建动画,用-addAnimation:forKey:
来开始动画,然后你停止它只要把它从layer上移除就好了,用-removeAnimationForKey:
或者 -removeAllAnimations
方法。
在我们去用不同的动画之前,让我们在和layer多玩会。一旦你创建了一个layer,你就必须给它一个位置并设置它的范围。然后,你可以更改许多层属性,最后,你必须将它添加到你的主视图层以使其可见。
好的,让我们试试这个:
Objective-C:
CALayer *layer = [[CALayer alloc] init];
[layer setPosition:CGPointMake(100.0, 200.0)];
[layer setBounds:CGRectMake(0.0, 0.0, 100.0, 120.0)];
[layer setCornerRadius:15.0];
[layer setBorderWidth:3.0];
[layer setBorderColor:[[UIColor redColor] CGColor]];
[layer setBackgroundColor:[[UIColor darkGrayColor] CGColor]];
[layer setOpacity:0.75];
[layer setShadowColor:[[UIColor blackColor] CGColor]];
[layer setShadowOffset:CGSizeMake(5.0, 5.0)];
[layer setShadowOpacity:.8];
[[self.view layer] addSublayer:layer];
[layer release];
既然CALayer是QuartzCore框架中的一部分,你就得把这框架加入到你的项目中去,并在需要的类中import一下。
Objective-C:
#import <QuartzCore/QuartzCore.h>
在上面的例子中,我试图设置一个层的所有属性,你现在可以试着把他们动画化,但是我们以后会看到的。在这之前,我想给你介绍一个重要的(并且被滥用)层属性:锚点。这是一件令人困惑的事。一个层的定位点的默认值是(0.5,0.5)。这代表了该层的中心。你必须把定位点想象成是层和上层之间的接触点。当你运用一些旋转的动画到你的视图上时,定位点是非常重要的,因为它是旋转的中心。如果将其设置为(0,0),并搞出一个旋转动画应用到该层,则该层将在其左上角旋转。
现在的问题是,当你改变锚点值,层重绘因为它改变了定位点的值。你需要使用以下代码来应用移位校正:
Objective-C:
CALayer *layer = [myView layer];
[layer setAnchorPoint:CGPointMake(1.0, 1.0)];
[layer setPosition:CGPointMake(layer.position.x + layer.bounds.size.width * (layer.anchorPoint.x - 0.5), layer.position.y + layer.bounds.size.height * (layer.anchorPoint.y - 0.5))];
第三行代码可以准确应用于任何有锚点改变带来的偏移。
现在想想这个。如果改变锚点到(0.0,0.5),然后让层沿X轴3D旋转,你会得到像在Flipboard(一款免费的应用程序,支持Android和iOS操作系统,将Facebook和新浪微博等社交媒体上的内容整合起来以杂志的形式呈现给用户阅读)里一样的效果。
下一次我们将和转换动画相伴,然后开始basic Animations基础动画。