Core Animation 基础 笔记

最近在学习CA部分东西,闲在就翻译了一下apple的这个CA的指南的基础部分,有机会再翻译其他的部分。限于水平,翻译不到位或者不足之处请指出。原文地址

基于层的绘图模型

     多数层并不做任何实际的绘图操作。相反,一个层会抓取你应用所提供的内容并把它缓存再位图中,有时候我们把这个位图称之为后备存储(backing stroe). 当后面你修改这个层的一个属性时,你所做的修改其实是修改了这个层对象所关联的状态信息。当一个修改触发了一个动画时,CA(Core Animation)将会把这个层的位图和状态信息给图像硬件,有硬件将新的信息来渲染这个位图。

     由于这个实际操作的是一个静态位图,所以基于层的绘图和基于视图的绘图模型有很大的区别。基于视图的绘图模型,修改视图常常会导致调用这个视图的drawRect:方法来重绘内容。但是使用这中方式是非常昂贵的,因为需要再主线程中由CPU来做这些事情。CA为了避免这种昂贵的操作,再任何可能的时候都通过硬件来操作缓存着的位图来达到一样或者近似效果的目的。


     尽管CA尽可能的使用缓存着的位图,但是你的应用必须要提供初始的内容和更新的时间。这里有几种方法为你的应用来提供层对象的内容。这个将会再“提供层内容”中详细描述。


基于层的动画

     一个层对象的数据和状态信息是从再屏幕上可见层内容解耦出来的。这种解耦使得CA有一种方法来再CA和从旧状态到新状态改变的动画做一下干预。比如说,要修改一个层的position属性将会导致CA将这个层的当前位置移动到一个新指定的位置上去。同样,修改启动的属性也导致一些合适的动画。下图1-2说明了一些可以在层上操作的动画类型。至于层的数据列表以及触发的动画,请查阅“动画属性”部分。




     在这个动画教学中,CA都是通过硬件来完成一帧帧的绘制。所有你要做的操作就是指明动画开始和结束的位置,之后的事情就有CA来完成。如果需要的话,你也可以指定自定义的时间信息和动画参数,通常,CA都已经默认为我们提供了合适的值。如果初始化动画,已经设置动画参数的更为详细的内容可以参阅“动画层内容”


层对象有他们自己的几何图形

     一个层的其中的一个工作就是管理它内容的可视几何图形。可视几何图形包含有关于内容的bounds信息,在屏幕上面的position信息,层是否有旋转,缩放,变换。和视图一样的是,一个层也有frame,bounds矩形用来设置layer的内容和位置。层还有视图所没有属性,比如锚点(anchor point),用来定义围绕一个点进行的操作。对层进行设置几何信息是和视图的信息是不同的。


层使用了2种坐标系

     层使用了基于点的坐标系和单位坐标系来指定内容的位置。依赖于传送来的信息类型决定使用哪种坐标系。如果将指定的值直接映射到屏幕坐标系或者必须指定了相对于另外一个层值,比如层的position属性就会使用基于点坐标系。如果值不应该和屏幕坐标系扯上关系就应该使用单位坐标系,因为它和其他一些值相关。比如层的anchorPoint属性指定了一个和层的bounds相关的一个点。

     其中使用点坐标系最多的就是用来指定层的大小和位置,这个可以通过设置层的bounds和positon属性进行。bounds定义了层的坐标系,以及在屏幕上面的大小。position属性定义了层相对于父坐标系的位置。尽管层也有frame属性,这个属性实际上是从bounds和posiont属性算出来的,这个使用的频率很低。


     一个层的bounds和frame的方向总是和默认的底层平台方向是一致的。图1-3显示的是默认ios和osx的bounds方向。在ios中原点的位置在左上角,而在osx中原点的位置在左下角。如何你需要在ios和osx之间共享CA代码的话,你必须要将它们之间的区别考虑在内。




     在图1-3中需要注意的一点是position属性是位于层的中间。这个属性是用于定义基于层anchorPoint变化属性中的一个。锚点表示的是由特定坐标产生,将会在“锚点对几何图形操作的影响”中详细阐述。

     锚点是用单位坐标系来指定的属性中的一个。CA使用单位坐标系来描述哪些属性值可能在层的大小变化改变而改变。你可以认为单位坐标系用来指定在总的值中的百分比。每个坐标在单位坐标空间中的范围都是0.0到1.0之间。比如说,沿着x轴,左边坐标是0.0 右边左边是1.0.沿着y轴单位坐标方向依赖于平台,如图1-4所示。



Note: Until OS X10.8, thegeometryFlippedproperty was a way tochange thedefaultorientation

of a layer’s y-axis when needed. Use of this property was sometimes necessary to correct the

orientation of a layer when flip transforms were in involved. For example, if a parent view used a flip transform, the contents of its child views (and their corresponding layers) would often be inverted.In such cases, setting the geometryFlipped property of the child layers to YES was an easy way to correct the problem. In OS X 10.8 and later, AppKit manages this property for you and you should not modify it. For iOS apps, it is recommended that you do not use the geometryFlipped property at all.



所有坐标值,不是点就是单位坐标系指定的浮点数。浮点数可以允许你使用在普通点之间的数来指定精确位置。使用浮点数是很方便的事,特别是在打印或者在Retina屏幕(一个点可能代表多个像素点)上绘制。浮点数允许你忽略底层硬件的分辨率而只是指定你想要的精确值。


锚点对几何图形操作的影响


     一个层的相关的几何操作总是和层的锚点有关,可以通过访问层的anchorPoint属性获取。锚点的影响主要是在操作层的position和transform属性时需要特别注意。position属性的指定总是相对于层的锚点。对层的任何变换操作总是相对于锚点发生的。

     图1-5展示了如果改变锚点的值来影响position属性。尽管层在父层的bounds中没有移动,只是把层的锚点从层的中心已到层bounds的原点的位置来改变position属性。

     



     图1-6展示的是改变锚点的值来影响层的变化操作。当你在层上应用了一个旋转变换,旋转是围绕锚点进行的。因为锚点默认是在层的中心点上,所以这个旋转一般都是我们所望的效果。然而,如果我们改变锚点的值,那么这个旋转就会另外一番情况。



层可以在3D中操作

      每个层都有2个变换矩阵来操作层和内容。CALayer的transfrom属性来指定应用到层和它的子层上的变换。通常你使用这个属性来修改层本身。比如说,你可能使用这个属性来缩放、旋转层或者临时修改它的位置。sublayerTransform属性定义了额外的变换来只是应用到子层上,通常在一个场景上来添加一个透视效果被用到。

     变换是通过使用一个矩阵和坐标值相乘的操作来获取的新的坐标来表示已经变换过的点。由于CA数据值可以用3D来指定,每个坐标点都有4个数据和4x4的矩阵相乘就像1-7所示。在CA,这种变换通过CATransform3D来表示。幸运的是,你不需要修改这个结构中的元素来打到标准变换。CA提供为缩放、平移、旋转或者矩阵比较的函数集。除了使用这些函数来操作变换之外,CA还扩展了KVC支持,使得允许你能够使用key path来修改一个变换。修改一个key path 列表,请查阅“CATransfrom3D 关键路径”。


     图1-8展示了非常常见变换用的矩阵。通过乘以相同的变换矩阵得到一样坐标。对于其他变换,坐标修改完全依赖于矩阵。比如,如果想要仅仅沿着x轴平移,你需要气筒一个非0的tx平移矩阵成分,而让ty和tz都为0.对于旋转,你就需要为旋转的角度提供合适的sin和cos值。


     关于这些使用这些函数来穿件和操作变换,请查阅CoreAnimationFunction Reference。

层树反应了动画状态的不同方面

       一个应用app在使用CA都会有3个层对象集合。每个层对象集合在让你的app展示在屏幕上起着不同的角色。

  • 模型树(简称为层树)中的对象,你交互最多的对象。这个树中的对象都是模型对象用来保持任意变换的目标值。任何时候你修改了一个层的属性,你都会使用这其中的对象。
  • 呈现树中对象包含有运行中动画的数值。然而模型树对象包含有动画的目标值,呈现树中的对象反应了在屏幕上呈现的当前值。你永远不要去修改这个树中的对象。相反,你应该使用这些对象来获取当前动画数值,这样可以你在某个值时来创建一个新的动画。
  • 渲染树中的对象负责执行实际的动画,它们在CA中是似有的。

     每种层对象都被层次结构的方式管理着,就像和应用中的视图管理方式一样。其实,每个app中的视图都有对应的层,在初始时,层树的结构和视图的层次结构是一样的。然而,一个app可以添加额外的层对象,换句话说,层并没有一定和视图相关联的。如果你想要对那些不需要所有一个视图内容时的性能优化时有必要的。图1-9展示了在ios中的一个简单app的层结构。样例中的window包含有一个内容视图,这个内容视图又包含有一个button视图和2个独立的层对象。每个视图都有对象的层对象组成了一个层分层结构。


在模型树中的每个对象,都有一个与之匹配的呈现树和渲染树,就像在图1-10中显示的一样。就像我们之前提到的,app的主要工作对象是哪些模型树中的对象,但是有时需要访问呈现树中的对象。特别的是访问模型树对象的presentationLayer属性来得到对应的呈现树对象。你可能需要访问一个运行中的动画中的一个属性的当前值。




重要:你应该在动画运行是去访问呈现树中的对象。在动画运行时,呈现树中的层值就是显示在屏幕上的实时的数值。这个行为和模型树是不同的,在模型树中总是反应的是在代码中设置的最后一个值,也是动画最终状态的数值。



层和视图的关系


     层并不是为了取代视图,也就是说,你不能创建一个只是基于层对象的可视接口。层为视图提供的了基础,层是的更方便更高效的去绘制和视图动画效果,并维持一个高的帧数。然而,层也有很多层所做不了的事情。层并不处理事件,绘制内容以及参与相应链等等事情。因为这个原因,每个app必须有哥一个或者多个视图去处理那些类似的交互。


     在iOS中,每个视图都有对应的一个层对象。但是在OS X中你必须决定哪个视图有层。在OS X v10.8及之后的版本,为所有的视图都添加层可能是有意义的。然后,你可能并不需要这么做,如在那些不必要的消耗就让layer保持不可用状态。层会增加app的内存消耗,但是这种方式的优点压倒缺点。所以在让层不可用时最好先测试一样app的性能再做决定。

     当你要让层可能来支持视图时,你会创建一个称之为后备层的视图(layer-backed view).在layer-backed view,系统会为之创建一个底层的层对象并保持和这个视图同步。在iOS中所有的视图都是layer-bakced view,在大多数OS X中也时layer-backed view.然后在OS X中,你也可以创建一个layer-hosting view,你想要自己提供层对象时可以创建这样视图。对于layer-hosting view,AppKit在视图修改时只是管理层但是并不对其进行修改。



注意:对于layer-backed view,建议你操作视图而不是去操作layer。在iOS中,视图时一个围绕层对象的简单封装,所以对层的任意操作通常都会运行的很好。但是在iOS和OS X中一些情况下应该操作层对象而不是视图………


     除了层和视图有关联,你也可以创建没有关联视图的层对象。你可以将这些独立的层对象嵌入到热议的层对象中,包括那些关联了视图的层对象。比如,如果你想要使用相同的图片在不同的地方,你可以只加载图片一次,和其他独立的层对象关联,并把这些对象添加到模型树上。然后每个层都引用了源图片而不是视图去创建内存的一份拷贝。


     关于如何去让层支持视图相关详细信息,请参阅“让CA支持你的app”,如果去创建一个层对象,以及在什么情况下使用这些的提示,请参阅“构建层的分层结构”。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值