对于 UIView 的 frame,bounds,center 都比较熟悉:
bounds指定 UIView 自身坐标系。center指定 UIView 在 superview 中的位置坐标。frame由互不影响(正交)的bounds跟center生成。
但是我一直有这样的疑问:为什么要使用 UIView 中心位置的 center 来指定坐标,为什么不用其他位置?
后来学习了 CALayer,发现 UIView 的主要任务其实是响应事件(这就是为什么从 UIResponser 继承的原因),而将显示委托给 CALayer 处理。一个成功的 UIView 背后总有一个默默贡献的 CALayer,CALayer 作为 GPU/OpenGL 纹理的一种高层封装,处理显示的方方面面,UIView 则将 CALayer 一些功能再次封装,提供简洁好用的接口。像 UIView 中的 frame,bounds 就是直接使用 CALayer 中的 frame,bounds。
但是对于 center,CALayer 对应项是 position,为什么不同名了呢?因为 position 更灵活,谁规定“指定 UIView 在 superview 中的位置坐标”一定要在 UIView 的中心位置呢?!而 position 默认在中心位置的目的我觉得是为了方便 Rotation,因为一般 Rotation 都是绕着中心旋转,UIView 为了简化使用,满足大部分情况即可,所以就将默认在中心的 position 封装成了 center。
由于 CALayer 的 position 并没有限制一定要在 bounds 的中心位置,所以就需要一个属性来描述 position 在 bounds 中的位置,这样才能推算出 frame 的 origin 点位置。于是 anchorPoint 出现了,CALayer 用 anchorPoint 指定 position 在 bounds 中的位置,有如下特点:
- 为了可以任意指定位置,因此
anchorPoint就不使用绝对值,而是比例值。 - 由于 Rotation 总是围绕
position旋转,因此指定position在 Layer 中位置的anchorPoint就被命名为锚点(像船的锚一样固定位置)。
总之,frame 是由 position,bounds,anchorPoint 共同生成(其实还有 transform,这就需要了解 Current Transform Matrix 的概念,为了减少复杂性,这里就不涉及了),公式如下:
- frame.origin.x = position.x - bounds.size.width * anchorPoint.x
- frame.origin.y = position.y - bounds.size.height * anchorPoint.y
这就解释了:
- 为什么 anchorPoint 改变会导致 frame 改变,而 position 却没变?
- 为什么 anchorPoint 要使用比例而不是具体值?
豁然开朗。
PS. 多思考,保持好奇心,多从设计者角度想想为什么这样设计,即使是简单的概念,也会有收获。Stay Hungry,Stay Foolish。




