引言

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

每一个UIView都默认关联着一个CALayer, UIView有frame、bounds和center三个属性,CALayer也有类似的属性,分别为frame、bounds、position、anchorPoint。那position、anchorPoint是什么呢?先看看两者的原型,可知都是CGPoint点。

 @property CGPoint position ;

 @property CGPoint anchorPoint ;

anchorPoint

一般都是先介绍position,再介绍anchorPoint。这里反过来,先来说说anchorPoint。

从一个例子开始入手吧,想象一下,把一张A4白纸用图钉订在书桌上,如果订得不是很紧的话,白纸就可以沿顺时针或逆时针方向围绕图钉旋转,这时候图钉就起着支点的作用。

我们要解释的anchorPoint就相当于白纸上的图钉,它主要的作用就是用来作为变换的支点,旋转就是一种变换,类似的还有平移、缩放。

继续扩展,很明显,白纸的旋转形态随图钉的位置不同而不同,图钉订在白纸的正中间与左上角时分别造就了两种旋转形态,这是由图钉(anchorPoint)的位置决定的。

如何衡量图钉(anchorPoint)在白纸中的位置呢?

在iOS中,anchorPoint点的值是用一种相对bounds的比例值来确定的,在白纸的左上角、右下角,anchorPoint分为为(0,0), (1, 1),也就是说anchorPoint是在单元坐标空间(同时也是左手坐标系)中定义的。

类似地,可以得出在白纸的中心点、左下角和右上角的anchorPoint为(0.5,0.5), (0,1), (1,0)。

然后再来看下面图:

position

确切地说,position是layer中的anchorPoint点在superLayer中的位置坐标。因此可以说,
position点是相对suerLayer的,anchorPoint点是相对layer的,两者是相对不同的坐标空间的一个重合点。

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

理解与运用

因为 position点和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;
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;

ios开发讲解之anchorPoint和position详解的更多相关文章

  1. iOS开发——UI篇OC篇&SpriteKit详解

    SpriteKit详解 SpriteKit,iOS/Mac游戏制作的新纪元 这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或 ...

  2. iOS开发——UI篇OC篇&UIDynamic详解

    iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟 ...

  3. iOS开发——网络编程Swift篇&Alamofire详解

    Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AF ...

  4. iOS开发——控制器OC篇&UINavigationController&UITabBarController详解

    UINavigationController&UITabBarController详解 一:UINavigationController 控制器的属性: UINavigationControl ...

  5. iOS开发——实用篇&KVO与KVC详解

    KVO与KVC详解 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC ...

  6. iOS开发 - OC - block的详解 - 基础篇

    深入理解oc中的block 苹果在Mac OS X10.6 和iOS 4之后引入了block语法.这一举动对于许多OC使用者的编码风格改变很大.就我本人而言,感觉block用起来还是很爽的,但一直以来 ...

  7. iOS开发——UI篇OC篇&UIStackView详解

    UIStackView详解 一.继承关系.遵守协议.隶属框架及可用平台 UIStackView 类提供了一个高效的接口用于平铺一行或一列的视图组合.Stack视图使你依靠自动布局的能力,创建用户接口使 ...

  8. iOS开发——UI篇OC篇&UICollectionView详解+实例

    UICollectionView详解+实例 实现步骤: 一.新建两个类 1.继承自UIScrollView的子类,比如HMWaterflowView * 瀑布流显示控件,用来显示所有的瀑布流数据 2. ...

  9. iOS 开发之 -- UDID和UUID的详解

    老实说,搞了几年的ios开发了,对基础的概念,还是不牢固,整天都是为了赶进度而码代码,这里记录一下这两者的区别: UDID的全名为 Unique Device Identifier :设备唯一标识符. ...

随机推荐

  1. 卡了很久的bug

    背景:在一个简单的项目中,通过循环前端传来的一个数组,使用mongodb条件查询数据,将满足条件的数据push进一个新数组,并返回至前端. 问题:每次调试到第五行,会自动跳过,直接执行12行,打印出来 ...

  2. JavaScript笔记5-事件

    一.概述: 事件是可以被JavaScript侦测到的行为.网页中的每个元素都可以产生某些可以触发JavaScript函数的事件.相当于让标签在满足某种条件的时候,调用指定的方法. 二.常用事件 1:o ...

  3. GreenDao的简单使用说明(五)多表n:m

    在设计一些比较复杂的数据库结构的时候,我们会遇到表之间是n:m的关系,就是常说的多对多的关系,最常用的情况,就是用户权限这块,日常最常见的就是学生与老师的关系了,哪么我们来看一下GreenDao中如何 ...

  4. 【extjs6学习笔记】1.1 初始:创建项目

    创建工作空间 sencha generate workspace /path/to/workspace 使用sencha创建应用 sencha -sdk /path/to/sdk generate a ...

  5. Intellij IDEA项目添加资源文件

    添加了一个资源文件,但读取的时候出错了 prop.load(Config.class.getResourceAsStream("/resources/dbconfig.properties& ...

  6. 链接服务器"(null)"的 OLE DB 访问接口 "SQLNCLI10" 返回了消息 "Cannot start more transactions on this session."

    开发同事反馈一个SQL Server存储过程执行的时候,报"链接服务器"(null)"的 OLE DB 访问接口 "SQLNCLI10" 返回了消息 ...

  7. Python之查询最新的文件

    import os # 定义文件的目录 result_dir = r'E:\python\测试报告' lists = os.listdir(result_dir) # 重新按时间对目录下的文件进行排序 ...

  8. 到底什么样的ABAP系统能运行Fiori应用

    有朋友在微信上问我两个问题: S/4 fiori是标配吗? 如果是ERP R/3,可以激活fiori配置吗? 先回答第二个问题. 在Jerry的微信公众号文章SAP Fiori应用的三种部署方式曾经提 ...

  9. UVA 10954 Add All 全部相加 (Huffman编码)

    题意:给你n个数的集合,每次选两个删除,把它们的和放回集合,直到集合的数只剩下一个,每次操作的开销是那两个数的和,求最小开销. Huffman编码.Huffman编码对于着一颗二叉树,这里的数对应着单 ...

  10. 3. Netbackup 7.6客户端的安装(windows/linux)

    1 客户端的安装 1.1 Windows客户端安装 1.1.1 客户端hosts修改 windows xp/2003/vista/2008/7/8用户HOSTS文件是在“c:\windows\syst ...