IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    通过实例来理解position与anchorPoint

    wonderffee发表于 2013-10-14 22:58:00
    love 0

    上一篇文章写了一些对position与anchorPoint的理解,这次就拿一些实例来加深印象。文中的例子来自别人的一篇博文,例子是不错的,但是自己刚开始也没完全搞明白,现在完全弄懂了,在这里借用一下并加以扩展,希望对看到的人有所帮助。

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

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

    1.创建一个CALayer,添加到控制器的view的layer中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    CALayer *myLayer = [CALayer layer];
    // 设置层的宽度和高度(100x100)
    myLayer.bounds = CGRectMake(0, 0, 100, 100);
    // 设置层的位置
    myLayer.position = CGPointMake(100, 100);
    // 设置层的背景颜色:红色
    myLayer.backgroundColor = [UIColor redColor].CGColor;
    
    // 添加myLayer到控制器的view的layer中
    [self.view.layer addSublayer:myLayer];
    

    第5行设置了myLayer的position为(100, 100),又因为anchorPoint默认是(0.5, 0.5),所以最后的效果是:myLayer的中点会在父层的(100, 100)位置。

    My Note:根据anchorPoint默认为(0.5, 0.5)以及结论3中的的公式,可以得到frame.origin为(50, 50),所以myLayer在图中左上角的位置应为(50, 50)。见下图:

    2.若将anchorPoint改为(0, 0)

    1
    
    myLayer.anchorPoint = CGPointMake(0, 0);
    

    MyNote:根据结论2,修改anchorPoint不影响position,则frame.origin需要重新计算,如下:

    1
    2
    
    frame.origin.x = 100 - 0 * 100 = 100;
    frame.origin.y = 100 - 0 * 100 = 100;
    

    这样,myLayer的左上角就会就会移动到(100, 100)的位置。见下图:

    3.若将anchorPoint改为(1, 1)

    1
    
    myLayer.anchorPoint = CGPointMake(1, 1);
    

    MyNote:同上,直接重新计算frame.origin,会得到frame.origin为(0, 0),myLayer左上角移动到(0, 0)的位置,见图:

    4.将anchorPoint改为(0, 1)

    1
    
    myLayer.anchorPoint = CGPointMake(0, 1);
    

    MyNote:类似地,直接重新计算frame.origin,会得到frame.origin为(100, 0),myLayer左上角移动到(100, 0)的位置,见图:

    5.设置frame与bounds的区别

    先看代码1:

    1
    2
    3
    4
    5
    
    CALayer *myLayer1 = [CALayer layer];
    myLayer1.bounds = CGRectMake(0, 0, 100, 100);
    myLayer1.anchorPoint = CGPointZero;
    myLayer1.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:myLayer1];
    

    再看代码2:

    1
    2
    3
    4
    5
    
    CALayer *myLayer2 = [CALayer layer];
    myLayer2.frame = CGRectMake(0, 0, 100, 100);
    myLayer2.anchorPoint = CGPointZero;
    myLayer2.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:myLayer2];
    

    区别在于第二行代码一个使用bounds,一个使用frame, 猜猜myLayer1和myLayer2左上角的位置会相同吗?

    你可能觉得是相同的,但其实不同,myLayer1左上角在(0, 0)点,myLayer1却不是预期的(0, 0)点,而是在(50, 50)点,也就是例1中的图,为什么?有人可能还会说我明明想将myLayer2左上角放在原点,怎么就不是呢?

    关键在于用的是frame。对于一个还没有superLayer的layer来说,position和anchorPoint都是有默认值的,分别为(0, 0)和(0.5, 0.5),如果对该layer设置了frame,因为anchorPoint还是保持默认值不会变化,只能是position随之变动。所以根据3中的公式,position的计算如下:

    1
    2
    
    position.x = 0 + 0.5 * 100 = 50
    position.y = 0 + 0.5 * 100 = 50
    

    position被确定为(50, 50),接着在代码2中又修改anchorPoint为(0, 0), 这个时候不影响position的值,只能是frame.origin被修改,也就是变成下面的:

    1
    2
    
    frame.origin.x = 50 - 0 * 100 = 50;
    frame.origin.y = 50 - 0 * 100 = 50;
    

    所以对一个已经确定frame的layer来说,再修改anchorPoint就会修改layer的位置,如果只想修改anchorPoint而不改变layer的位置,就用代码1的方式来进行,或者把代码2中设置frame与anchorPoint的代码顺序调换一下,就能解决问题。

    要记住的就是设置frame会隐式修改position,而默认的anchorPoint从来不会被隐式修改,只能被显式修改。

    参考

    • position和anchorPoint
    • Changing my CALayer’s anchorPoint moves the view


沪ICP备19023445号-2号
友情链接