引言

相信初接触到CALayer的人都会遇到以下几个问题:  
为什么修改anchorPoint会移动layer的位置? 
CALayer的position点是哪一点呢? 
anchorPoint与position有什么关系?

每一个UIView内部都默认关联着一个CALayer, UIView有frame、bounds和center三个属性,CALayer也有类似的属性,分别为frame、bounds、position、anchorPoint。frame和bounds比较好理解,bounds可以视为x坐标和y坐标都为0的frame,那position、anchorPoint是什么呢?先看看两者的原型,可知都是CGPoint点。

@property CGPoint position 
@property CGPoint anchorPoint

anchorPoint

从一个例子开始入手吧,想象一下,把一张A4白纸用图钉订在书桌上,如果订得不是很紧的话,白纸就可以沿顺时针或逆时针方向围绕图钉旋转,这时候图钉就起着支点的作用。我们要解释的anchorPoint就相当于白纸上的图钉,它主要的作用就是用来作为变换的支点,旋转就是一种变换,类似的还有平移、缩放。

继续扩展,很明显,白纸的旋转形态随图钉的位置不同而不同,图钉订在白纸的正中间与左上角时分别造就了两种旋转形态,这是由图钉(anchorPoint)的位置决定的。如何衡量图钉(anchorPoint)在白纸中的位置呢?在iOS中,anchorPoint点的值是用一种相对bounds的比例值来确定的,在白纸的左上角、右下角,anchorPoint分为为(0,0), (1, 1),也就是说anchorPoint是在单元坐标空间(同时也是左手坐标系)中定义的。类似地,可以得出在白纸的中心点、左下角和右上角的anchorPoint为(0.5,0.5), (0,1), (1,0)。

然后再来看下面两张图,注意图中分iOS与MacOS,因为两者的坐标系不相同,iOS使用左手坐标系,坐标原点在左上角,MacOS使用右手坐标系,原点在左下角,我们看iOS部分即可。

  
图1

  
图2

像UIView有superView,与subView的概念一样,CALayer也有superLayer与layer的概念,前面说到的白纸和图中的矩形可以理解为layer,书桌和图中矩形以外的坐标系可以理解成superLayer。如果各自以左上角为原点,则在图中有相对的两个坐标空间。

position

在图1中,anchorPoint有(0.5,0.5)和(0,0)两种情况,分别为矩形的中心点与原点。那么,这两个anchorPoint在superLayer中的实际位置分别为多少呢?简单计算一下就可以得到(100, 100)和(40, 60),把这两个值分别与各自的position值比较,发现完全一致,该不会是巧合?

这时候可以大胆猜测一下,position是不是就是anchorPoint在superLayer中的位置呢?答案是确定的,更确切地说,position是layer中的anchorPoint点在superLayer中的位置坐标。因此可以说, position点是相对suerLayer的,anchorPoint点是相对layer的,两者是相对不同的坐标空间的一个重合点。

再来看看position的原始定义: The layer’s position in its superlayer’s coordinate space。 
中文可以理解成为position是layer相对superLayer坐标空间的位置,很显然,这里的位置是根据anchorPoint来确定的。

图2中是矩形沿不同的anchorPoint点旋转的形态,这就是类似于刚才讲的图钉订在白纸的正中间与左上角时分别造就了两种旋转形态。

anchorPoint、position、frame

anchorPoint的默认值为(0.5,0.5),也就是anchorPoint默认在layer的中心点。默认情况下,使用addSublayer函数添加layer时,如果已知layer的frame值,根据上面的结论,那么position的值便可以用下面的公式计算:

position.x = frame.origin.x + 0.5 * bounds.size.width;
position.y = frame.origin.y + 0.5 * bounds.size.height;

里面的0.5是因为anchorPoint取默认值,更通用的公式应该是下面的:

position.x = frame.origin.x + anchorPoint.x * bounds.size.width;
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;

下面再来看另外两个问题,如果单方面修改layer的position位置,会对anchorPoint有什么影响呢?修改anchorPoint又如何影响position呢?  
根据代码测试,两者互不影响,受影响的只会是frame.origin,也就是layer坐标原点相对superLayer会有所改变。换句话说,frame.origin由position和anchorPoint共同决定,上面的公式可以变换成下面这样的:

frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;

这就解释了为什么修改anchorPoint会移动layer,因为position不受影响,只能是frame.origin做相应的改变,因而会移动layer。

理解与运用

在Apple doc对frame的描述中有这么一句话:

Layers have an implicit frame that is a function of the position, bounds, anchorPoint, and transform properties.

可以看到我们推导的公式基本符合这段描述,只不过还缺少了transform,加上transform的话就比较复杂,这里就不展开讲了。


Apple doc中还有一句描述是这样的:

When you specify the frame of a layer, position is set relative to the anchor point. When you specify the position of the layer, bounds is set relative to the anchor point.

大意是:当你设置图层的frame属性的时候,position根据锚点(anchorPoint)的值来确定,而当你设置图层的position属性的时候,bounds会根据锚点(anchorPoint)来确定。

这段翻译的上半句根据前面的公式容易理解,后半句可能就有点令人迷惑了,当修改position时,bounds的width与height会随之修改吗?其实,position是点,bounds是矩形,根据锚点(anchorPoint)来确定的只是它们的位置,而不是内部属性。所以,上面这段英文这么翻译就容易理解了:

当你设置图层的frame属性的时候,position点的位置(也就是position坐标)根据锚点(anchorPoint)的值来确定,而当你设置图层的position属性的时候,bounds的位置(也就是frame的orgin坐标)会根据锚点(anchorPoint)来确定。

在实际情况中,可能还有这样一种需求,我需要修改anchorPoint,但又不想要移动layer也就是不想修改frame.origin,那么根据前面的公式,就需要position做相应地修改。简单地推导,可以得到下面的公式:

positionNew.x = positionOld.x + (anchorPointNew.x - anchorPointOld.x)  * bounds.size.width
positionNew.y = positionOld.y + (anchorPointNew.y - anchorPointOld.y)  * bounds.size.height

但是在实际使用没必要这么麻烦。修改anchorPoint而不想移动layer,在修改anchorPoint后再重新设置一遍frame就可以达到目的,这时position就会自动进行相应的改变。写成函数就是下面这样的:

- (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{CGRect oldFrame = view.frame;view.layer.anchorPoint = anchorpoint;view.frame = oldFrame;
}

总结

1、position是layer中的anchorPoint在superLayer中的位置坐标。 
2、互不影响原则:单独修改position与anchorPoint中任何一个属性都不影响另一个属性。 
3、frame、position与anchorPoint有以下关系:

frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;

第2条的互不影响原则还可以这样理解:position与anchorPoint是处于不同坐标空间中的重合点,修改重合点在一个坐标空间的位置不影响该重合点在另一个坐标空间中的位置。

转载于:https://www.cnblogs.com/moxuexiaotong/p/4914332.html

理解position与anchorPoint[转]相关推荐

  1. 48.iOS动画和理解position与anchorPoint

    1.动画的基本概念 动画的使⽤场景:iOS中的动画是指一些视图上的过渡效果,合理利用动画能提⾼用户体验,UIView动画影响的属性 frame:视图框架 center:视图位置 alpha:视图透明度 ...

  2. 彻底理解position与anchorPoint - Wonderffee's Blog(转)

    引言 相信初接触到CALayer的人都会遇到以下几个问题:  为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与posi ...

  3. 彻底理解position与anchorPoint

    引言 相信初接触到CALayer的人都会遇到以下几个问题:  为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与posi ...

  4. 简单的理解position与anchorPoint

    很多人都搞不清楚这两个点,其实这两个点还是不难理解的,用一句话就能概括 anchorPoint 表示这个点在 自身layer 中的位置, position 表示这个点在父layer中的位置 1. an ...

  5. iOS: 彻底理解position与anchorPoint

    http://wonderffee.github.io/blog/2013/10/13/understand-anchorpoint-and-position/

  6. position与anchorPoint理解(一)

    转自 彻底理解position与anchorPoint 关于CALayer和UIView的介绍请移步:CALayer与UIView的关系 每一个UIView内部都默认关联着一个CALayer, UIV ...

  7. 彻底理解CALayer的position与anchorPoint

    引言 相信初接触到CALayer的人都会遇到以下几个问题:   为什么修改anchorPoint会移动layer的位置?  CALayer的position点是哪一点呢?  anchorPoint与p ...

  8. 如何理解:先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1的方法,即对于机器数为负数,则有[X]原=[[X]补]补。

    对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1的方法,即对于机器数为负数,则有[X]原=[[X]补]补. 当然你也可以用先减1后取反的方法来求补码对应的原码. 对于求 ...

  9. [翻译]Why Functional Programming Matters

    Why Functional Programming Matters 函数式程序设计为什么至关重要 作者: John Hughes 翻译: CloudiDust [http://blog.csdn.n ...

  10. 开源的悲哀——袁萌100天变身实录[2]

    承接上文:开源的悲哀--袁萌100天变身实录[1] 2008年2月末:赤裸裸的微软支持者! 2008年2月29日是ISO为OOXML设置"快速通道"的投票日,因此2月下旬成为OOX ...

最新文章

  1. 3dmax2014:打开3dmax2014软件时,出现许可证检出失败 错误20
  2. Newbe.Claptrap 框架入门,第一步 —— 开发环境准备
  3. leetcode 二进制求和 addBinary
  4. centos下载mysql_python数据分析之路——centos下载并配置mysql与navicat的使用
  5. Maven : Cannot deploy artifact from the local repository
  6. 移动12.1号动感地带寻宝答案
  7. 海德薇格:我很期待看到 数字货币将如何改变人民币支付市场
  8. 《『若水新闻』客户端开发教程》——03.设计新闻分类UI(1)
  9. python中安装decimal模块_第38天:Python decimal 模块
  10. 程序设计与c语言区别,c语言程序设计和c程序设计有什么区别啊
  11. H264编码器性能测试
  12. 电源完整性之Cadence Sigrity Power DC_电热协同仿真
  13. android+recovery+启动流程,Recovery启动流程(一)- 应用层到开机进入recovery详解
  14. 乡镇特色产业发展情况调研报告
  15. 【Linux】Centos设置Python的软链接
  16. 如何完整保存离线网页
  17. 关于 JSON,什么是JSON
  18. 关于软件测试你必须知道的名词
  19. sendgrid html text,在Node.js中的SendGrid的“发件人”字段中添加名称
  20. Mac系统下TestCafe初体验

热门文章

  1. Rejected request from RFC1918 IP to public server address
  2. hdu 4828 Grids(拓展欧几里得+卡特兰数)
  3. 华为的IPsec ×××主模式(MAIN mode)
  4. 通过程序得到数据库表之间的关联关系
  5. idm下载百度网盘有限制 提示403错误 下载显示没有权限404,最新的解决办法教程
  6. 可以做技术,切不可沉湎于技术,大家怎么看?
  7. 用工厂流水线的方式来理解 RxJava 的概念
  8. *第十六周*数据结构实践项目二【大数据集上排序算法性能的体验】
  9. *第七周*数据结构实践项目二【建设链式队列算法库】
  10. 7.4 集合及其内置方法