Ficow 陪你彻底搞懂 CALayer 里的 anchorPoint 和 position

| Swift , iOS , Core Animation

 

内容概览

  • 前言
  • anchorPoint 在此 layer 中决定自身坐标系的原点
  • position 决定此 layer 自身坐标系原点在父 layer 中的位置
  • 总结与温馨提示

 

前言

 

最近有同事在研究 Core Animation 的动画,这个动画需要将视图进行伸缩。具体的效果就像把投影仪的投影幕布从上往下展开然后再从下往上收起。这种情况就需要用 anchorPoint 将 layer 的锚点设置到顶部,然后动画就会以顶部为固定点来进行伸缩。

下面是效果图(蓝色块):

然而,这个工作进展地并不顺利。因为同事需要在刷新 UITableViewCell 的时候让 cell 内部的子视图进行动画,这时候动画和布局都出现了一些问题。于是,我意识到我们对于 anchorPoint 的理解是有问题的。所以,就开始进行深入的研究。于是,就有了这一篇文章。

Ficow 希望本文可以让您彻底理解 anchorPointposition,然后尽情地享受动画带给您的快乐~

 

下图展示的是本文相关的示例项目。如果您感兴趣,您可以在 这个 Github 仓库 中查看相关的代码。

 

anchorPoint 在此 layer 中决定自身坐标系的原点

 

anchorPoint 属性在官方文档中的定义:

Defines the anchor point of the layer’s bounds rectangle.
定义 layer 的 bounds 矩形的锚点。

我们知道 bounds 是由 layer 自身坐标空间来决定的。所以,理解 anchorPoint 就需要先理解 layer 自身的坐标空间。

 

首先,下面是一张来自苹果官方的图解。默认情况下,anchorPoint 等于 (0.5, 0.5),此时的 anchorPoint 在 layer 的中心位置。

然后,图解中的第二行将 anchorPoint 设置为了 (0.0, 0.0)。如果是在 iOS 中,此时的 anchorPoint 在 layer 的左上角。如果是在 OS X 中,此时的 anchorPoint 在 layer 的左下角。

请注意,boundsframe 参数都没有发生变化,但是 position 却变了!如果 anchorPoint 变了,而 position 不变,那么第二行的橙色框的原点将是 (100.0, 100.0),也就是 position 所在的位置。

如下图所示:

 

Ficow 是这样理解的,anchorPoint 在 layer 内部决定了此 layer 自身坐标系原点的位置,而 position 决定了此 layer 自身坐标系原点在父 layer 中的位置。在这个 layer 中,anchorPointposition 其实是同一个点。

 

如果上面的解释无法让您理解,那就让我们再来看一张苹果官方的图解:

layer 会绕着 anchorPoint 旋转,anchorPoint 就是旋转时的圆心。因为,它是 layer 自身坐标系的原点!

即使是 layer 被旋转了,anchorPointposition 还是在同一个位置。因为,它们是同一个点!

 

position 决定此 layer 自身坐标系原点在父 layer 中的位置

 

position 属性在官方文档中的定义:

The layer’s position in its superlayer’s coordinate space.
此 layer 在其父 layer 坐标空间中的位置。

所以,改变 position 就可以改变 layer 在父 layer 中的位置。这也是它被命名为 position 的原因。

 

接下来,Ficow 将通过一些示例来演示 position 的作用效果,以此来帮助您理解它。示例中的 animationView 是蓝色的块,containerView 是灰色的背景。

 

将 animationView 放置到左上角

将 animationView 放置到左上角

        animationView.layer.anchorPoint = .init(x: 0, y: 0) // 定位到自身左上角
        animationView.layer.position = containerView.bounds.origin // 定位到父视图的左上角

 

将 animationView 放置到右下角

将 animationView 放置到右下角

        animationView.layer.anchorPoint = .init(x: 1, y: 1) // 定位到自身右下角
        animationView.layer.position = .init(x: containerView.bounds.maxX, y: containerView.bounds.maxY) // 定位到父视图的右下角

请注意,当您更改 anchorPoint 时,您还需要及时地调整 position。否则,最终结果可能并不是您期望的那样。

 

总结与温馨提示

 

通过官方文档和各种实验,我们可以得出如下总结:

  • anchorPoint 在 layer 内部决定了此 layer 自身坐标系原点的位置,而 position 在父 layer 中决定了此 layer 自身坐标系原点的位置。
  • anchorPointposition 处于同一个点。
  • 更改 anchorPoint 后,还需要及时地调整 position 来将 layer 放置到父 layer 中正确的位置。

 

此外,Ficow 还有一些关于做动画的温馨提示:

  • 在每次开始做动画前调整 anchorPointposition,动画结束后就将其恢复正常值。否则,错误的 anchorPointposition 有可能会导致界面布局异常。
  • 通过 view 来使用 layer 做动画时,view 可能会移动 layer 的位置(比如:自动布局导致 view 的位置发生变化、cell 被刷新导致 view 的大小发生变化等),您需要在开始动画前确认 position 的值是否已设置正确。

 

如果您还有任何疑问,欢迎您给 Ficow 留言!我会尽力为您解答~

 

参考内容:
Core Animation Basics

 

觉得不错?点个赞呗~

本文链接:Ficow 陪你彻底搞懂 CALayer 里的 anchorPoint 和 position

转载声明:本站文章如无特别说明,皆为原创。转载请注明:Ficow Shen's Blog

评论区(期待你的留言)