iOS动画:寄宿图和图层几何

学习手记,每天进步一点!

CALayer相关属性

contents

CALayer有一个属性contents,这个属性是id类型,理论上可以赋任何值,实际上需要CGImage类型。可以使用contents属性在CALayer上显示图片,而不使用UIImageView

contentGravity

这个属性类似于UIImageViewcontentMode属性,解决内容在图层的边界中怎么对其。不同点是contentGravity是可选的字符串常量,而contentMode对应的值是枚举类型。

  • kCAGravityCenter
  • kCAGravityTop
  • kCAGravityBottom
  • kCAGravityLeft
  • kCAGravityRight
  • kCAGravityTopLeft
  • kCAGravityTopRight
  • kCAGravityBottomLeft
  • kCAGravityBottomRight
  • kCAGravityResize
  • kCAGravityResizeAspect
  • kCAGravityResizeAspectFill

contentsScale

contentsScale定义了寄宿图的像素尺寸和视图大小的比例。默认值是1.0。用来支持高分辨率屏幕,如果设置1.0,将会以每个点1个像素绘制图片,设置2.0,则会每个点2个像素绘制图片。

maskToBounds

maskToBounds决定内容超出图层部分是否显示。类似于UIView中的clipsToBounds属性。

contentsRect

CALayercontentRect属性允许在图层边框中显示寄宿图的一个子域。通过单位坐标设置值。默认的contentRect是{0,0,1,1},寄宿图默认全都可见。

contentRect可以用来实现图片拼接。将多张图片通过设置不同的contentRect设置不同图片的位置。

contentsCenter

contentsCenterCGRect,定义一个固定的边框和一个在图层上可以拉伸的区域。类似于UIImage中的resizableImageWithCapInsets:方法。可以在Interface Builder中修改Stretching设置contentsCenter属性。

自定义绘制

另一种设置寄宿图的方法,通过继承UIVIew并实现drawRect:方法来自定义绘制。

图层几何学

布局

UIView三个重要属性:frameboundscenterCALayer对应叫做frameboundsposition。为了区分,图层使用position,视图使用center,代表相同值。

frame代表图层的外部坐标(相对父图层),bounds代表图层内部坐标(通常{0,0}图层的左上角),centerposition代表相对父图层anchorPoint位置。

锚点

图层的anchorPoint通过position来控制它的frame的位置,可以认为anchorPoint是用来移动图层的把柄。
[站外图片上传中…(image-5586e1-1512351447938)]

坐标系

图层坐标系和视图一样,图层的position依赖于父图层的bounds,如果父图层发生移动,它的所有子图层也会跟着移动。

CALayer给不同坐标系之间的图层转换提供了一些工具类方法:

1
2
3
4
5
6
7
open func convert(_ p: CGPoint, from l: CALayer?) -> CGPoint

open func convert(_ p: CGPoint, to l: CALayer?) -> CGPoint

open func convert(_ r: CGRect, from l: CALayer?) -> CGRect

open func convert(_ r: CGRect, to l: CALayer?) -> CGRect

这些方法把定义在一个图层坐标系下的点或矩形转换成另一个图层坐标系下的点和矩形。

翻转的几何结构

在iOS中,图层的position位于父图层的左上角,但Mac OS上,位于左下角。Core Animation通过geometryFlipped属性来适配这两种情况,决定一个图层的坐标是否相对于父图层垂直翻转,是一个Bool类型。

Z坐标轴

CALayer除了positionanchorPoint属性之外,还有两个属性,zPositionanchorPointZ,二者都是Z轴上描述图层位置的浮点类型。通过修个zPosition值改变图层层级关系。

Hit Testing

CALayer不处理任何响应链事件,所以不能直接处理触摸事件或者手势。但是它有一些方法可以帮助处理事件:

1
2
3
4
5
6
7
/** Hit testing methods. **/
open func hitTest(_ p: CGPoint) -> CALayer?


/* Returns true if the bounds of the layer contains point 'p'. */

open func contains(_ p: CGPoint) -> Bool

contains(p:)判断p点是否在图层中,需要转换坐标。

hitTest(p:)顺序严格依赖于图层数的图层顺序,注意zPosition属性可以改变图层在屏幕上的显示顺序,但无法改变事件的传递顺序。

视觉效果

圆角(cornerRadius)

CALayer有一个叫做cornerRadius属性来控制图层角的曲率。如果把masksToBounds设置成true,图层里面的所有内容都会被截取。

图层边框(borderWidth/borderColor)

CALayer另外两个属性borderWidthborderColor。设置边框的宽度和颜色,borderColorCGColorRef类型,而不是UIColor

阴影

shadowOpacity设置阴影透明度。改变CALayer另外的属性:shadowColorshadowOffsetshadowRadius

  • shadowColor:控制阴影的颜色。
  • shadowOffset: 控制阴影的方向和距离,它是一个CGSize的值,宽度控制阴影横向的位移,高度控制纵向的位移。shadowOffset的默认值是{0,-3},即阴影相对于Y轴向上位移3像素。
  • shadowRadius控制阴影的模糊度,当值越大,边界线越2模糊和自然。

shadowPath属性

shadowPath是一个CGPathRef类型(CGPath的指针)。CGPath是一个Core Graphics对象,用来指定任意的一个矢量图形。

图层蒙版

maskToBounds属性,沿边界裁剪图形;CALayer的一个属性mask可以设置蒙版,该属性是一个CALayer类型,类似一个子图层,相对于父图层布局。蒙版不局限于静态图还可以动画实时生成。

拉伸过滤

minificationFilter(缩小图片)和magnificationFilter(放大图片)属性。视图显示图片的时候,都是以1:1像素在屏幕上显示。

当图片需要显示不同的大小的时候,可以使用拉伸过滤算法实现。它作用于原图的像素上根据需要生成新的像素显示在屏幕上。

三种拉伸过滤方法:

  • kCAFilterLinear(双线性滤波算法)
  • kCAFilterNearest
  • kCAFilterTrilinear

后两者相似,较双线性滤波算法而言,三线性滤波算法存储了多个大小情况下的图片(也叫多重贴图),并三维取样,同时结合大图和小图的存储进而得到最后的结果。

组透明

UIView有一个alpha的属性确定视图的透明度。CALayer等同的属性叫做opacity,两个属性都是影响子层级的。

CALayer有一个shouldRasterize属性来实现组透明的效果。图层的rasterizationScale属性匹配屏幕,以防止出现Retina屏幕像素化的问题。

小结