图层几何学
视图和图层布局差异
- 视图上的
center
,在图层上对应叫position
-
center
和position
都代表了当前图层相对于父图层anchorPoint
的位置 - 视图改变
frame
的实质是改变图层的frame
-
frame
是根据bounds
,position
和transform
计算而来,所以当其中任何一个值发生改变,他都会变化。相反,改变frame
的值同样会影响到他们当中的值 -
frame
的宽高可能和bounds
不一致,比如视图旋转后
anchorPoint属性 - 锚点
- 锚点可以理解为视图的把柄,缩放移动旋转等操作,会相对于锚点进行
-
anchorPoint
通过单位坐标描述,默认值是{0.5, 0.5}(图层中心) -
anchorPoint
发生了改变但是position
没有改变,所以图层会重新布局,frame
会发生改变 -
anchorPoint
改变后,建议重新设置frame
或position
坐标系操作
- CALayer提供了点或矩形在不同图层坐标系间转化的方法
- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
- 可以通过设置
geometryFlipped
翻转整个坐标系,他是BOOL型的
图层的三维坐标
- 图层有
zPosition
和anchorPointZ
来描述在Z轴上的位置 - 图层是一个完全扁平的对象,并没有更多属性来描述他在Z轴上的高度了
- 图层的
zPosition
除了使用CATransform3D来渲染3D动画,还可以用来调整图层的显示顺序,通常图层的显示顺序,是使用“画家的算法”不断覆盖上去的,但通过改变zPosition
可以将图层顺序前置
图层HitTest
- CALayer并不关心任何响应事件但是它有一系列的方法帮你处理事件:
-containsPoint:
和-hitTest:
-
-containsPoint:
接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame
范围内就返回YES -
-hitTest:
方法同样接受一个CGPoint类型参数,但返回的不是BOOL类型,它返回图层本身,或者包含这个坐标点的叶子节点图层 -
-hitTest:
的测算的顺序依赖于图层树的顺序,和zPosition
改变后显示顺序无关。所以使用zPosition
改变图层显示顺序后,事件可能无法响应
视觉效果
圆角
-
conrnerRadius
属性控制着图层角的曲率 - 书中原话是这个曲率值只影响背景颜色而不影响背景图片或是子图层
-
masksToBounds
设置成YES的话,子图层超出父图层的区域会被裁剪
图层边框
-
borderWidth
描述了图层边框宽度,这个边框的绘制是沿裁剪后的图层边缘,并且绘制在图层边界里面的,而且在所有子内容之前,也在子图层之前 -
borderColor
描述了边框颜色信息
阴影
- 若需要增加阴影表现,只需要更改
shadowOpacity
属性,他是一个0.0(不可见)和1.0(完全不透明)之间的浮点数 - 若要改动阴影的表现,你可以使用CALayer的另外三个属性:
shadowColor
,shadowOffset
和shadowRadius
-
shadowRadius
控制了阴影的模糊度,当它的值是0的时候,阴影就和视图一样有一个非常确定的边界线。当值越来越大的时候,边界线看上去就会越来越模糊和自然。苹果的设计,更倾向于自然阴影,即值为0 - 阴影路径是根据寄宿图轮廓来确定的
- 阴影绘制在图层外部,所以
masksToBounds
设置成YES的话,阴影会被裁剪 - 如果想沿着内容裁切,又想保留阴影,需要用到两个图层:一个只画阴影的空的外图层,和一个用masksToBounds裁剪内容的内图层
- 如果在图层渲染前知道阴影形状会是什么样子的,可以指定一个
shadowPath
来提高性能
图层蒙版
- 通常创建一个无矩形视图最方便的方法,可以给它指定一个透明蒙板来实现,使用
mask
属性,这个属性所指向的类型就是CALayer -
mask
图层的color
属性是无关紧要的,真正重要的是图层的轮廓。mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃
拉伸过滤
-
当图片需要显示不同的大小的时候,有一种叫做拉伸过滤的算法就起到作用了。它作用于原图的像素上并根据需要生成新的像素显示在屏幕上
我的理解例如需要将一张20x20图显示在40x40的图层上,为了避免图片的像素化,通过过滤算法生成新的像素图
minificationFilter
和magnificationFilter
属性描述了在图片需要缩小或拉伸时所用的过滤器算法-
CALayer对图片的拉伸提供了三种算法
- kCAFilterLinear - 默认过滤器
- kCAFilterNearest - 效率非常快,但会使得压缩图片更糟,图片放大之后也显得块状或是马赛克严重
- kCAFilterTrilinear - 提高了性能,也避免了小概率因舍入错误引起的取样失灵的问题
-
如果是对于比较小的图或者是差异特别明显,极少斜线的大图,那么kCAFilterNearest既保证效率,同时又会保留最好的呈现效果
kCAFilterLinear和kCAFilterTrilinear的差异并不明显,如果是简单图,kCAFilterNearest将会是最优选择
组透明
UIView的
alpha
属性和CALayer的opacity
属性,这两个属性都是影响子层级的透明度的理想状况下,当设置了一个图层的透明度,希望它包含的整个图层树像一个整体一样的透明效果,但实际情况,有可能因为透明度的混合叠加造成的
为了避免透明度混合造成的视觉上的混乱,可以使用
shouldRasterize
属性,来实现组透明的效果。如果设置了这个属性,在应用透明度之前,图层及其子图层都会被整合成一个整体的图片-
如果使用了shouldRasterize属性,就要确保你设置了
rasterizationScale
属性去匹配屏幕,以防止出现Retina屏幕像素化的问题btn.layer.shouldRasterize = YES; btn.layer.rasterizationScale = [UIScreen mainScreen].scale;