iOS CALayer anchorPoint 的应用场景

背景

最近在看《ios核心动画高级技巧》,这本书的中文版本可以在iOS Core Animation: Advanced Techniques中文译本
这里找到,看到图形几何学这一章,其中讲到的 CALayeranchorPoint 属性,发现不是很了解,所以自己发了点时间做了些研究,做了点简单的总结,主要涉及到以下主题:

  • anchorPoint 是什么
  • anchorPoint 应用场景

本文的DemoDrawDemo

anchorPoint 是什么

图层的anchorPoint通过position来控制它的frame的位置,你可以认为anchorPoint是用来移动图层的把柄。

上面是《ios核心动画高级技巧》书中对 anchorPoint 的解释,只看概念可能会不好理解,下面用两个例子来解释anchorPoint的概念。

例一:修改了anchorPoint 对图层的影响

如图所示,创建一个Frame为(100, 200, 100, 100)的蓝色layer,橙色的layer是修改了anchorPoint为CGPointMake(1, 1)之后的结果

修改anchorPoint对图层的影响1

1、分析蓝色layer
默认的anchorPoint是(0.5, 0.5),位于layer的中间,position也是位于layer的中间,layer以中心点为定位点,此时positon的意义是 layer的中心点距离父layer的原点的位置是position.x,position.y ,所以最终的frame位置如图所示为 {{100, 100}, {100, 100}}

2、分析橙色layer
anchorPoint是(1, 1),位于layer的右下角,position也是位于layer的右下角,layer以右下角为定位点,此时positon的意义是 layer的右下角距离父layer的原点的位置是position.x,position.y ,所以最终的frame位置如图所示为 {{50, 50}, {100, 100}}

3、两个重要的结论

  1. anchorPoint和position是一一对应的,anchorPoint是相对于layer自身的,是一个单位坐标 (0~1, 0~1) ,表示当前layer的定位点是位于layer的什么位置,定位点决定了layer相对于父layer的关系以及layer的旋转中心,后面会有旋转的例子
  2. 只修改了anchorPoint不会使position变化,但是图层位置会变化,因为定位点的位置改变了,导致最终Layer的Frame改变了,Frame是最终决定Layer位置的。

例子的代码如下:

// anchorPoint 对图层的影响
    layer = [[CALayer alloc] init];
    layer.frame = CGRectMake(100, 200, 100, 100);
    layer.borderColor = [UIColor blueColor].CGColor;
    layer.borderWidth = 1;
    layer.anchorPoint = CGPointMake(0.5, 0.5);
    [self.view.layer addSublayer:layer];
    NSLog(@"layer position = %@, anchorPoint = %@  frame = %@", NSStringFromCGPoint(layer.position), NSStringFromCGPoint(layer.anchorPoint), NSStringFromCGRect(layer.frame));

    {
        CALayer* copyLayer = [self cloneLayer:layer];
        copyLayer.borderColor = [UIColor orangeColor].CGColor;
        [self.view.layer addSublayer:copyLayer];
        // 默认的anchorPoint位置为(0.5, 0.5),和position是对应的
        // 需要移动anchorPoint到layer的右下角,
        // 假设认为anchorPoint的位置是固定的,怎样才能把anchorPoint定位到位置为(1, 1)
        // 需要把整个的layer往上和往左移动(layer.width * 0.5)个点才能够做到
        // 这样会导致frame的origin的变化,也就是layer会往左上角偏移了
        // position的值没有改变,anchorPoint位置是对应的,下面会进行谈论
        copyLayer.anchorPoint = CGPointMake(1, 1);
        NSLog(@"layer position = %@, anchorPoint = %@  frame = %@", NSStringFromCGPoint(copyLayer.position), NSStringFromCGPoint(copyLayer.anchorPoint), NSStringFromCGRect(copyLayer.frame));
        
        // 回到这里,继续讨论anchorPoint引起的frame的变化而position不变
        // anchorPoint是layer定位点(包括旋转和缩放,是相对于layer自身的,是一个单位坐标的点)
        // position是和anchorPoint对应的点,是layer相对于父layer的定位点,
        // anchorPoint=(0.5, 0.5),layer的中心位置相对于父layer原点的位置为position
        // 因为在只修改anchorPoint的情况下不改变position的值,所以:
        // anchorPoint=(1, 1),layer的右下角位置相对于父layer原点的位置为position
    }

例二:Frame不变,修改了anchorPoint 对图层的影响

如图所示,创建一个Frame为(100, 300, 100, 100)的蓝色layer,橙色的layer是修改了anchorPoint为CGPointMake(0, 0)之后但是Frame不变的结果,红色的layer是修改了anchorPoint为CGPointMake(1, 1)之后但是Frame不变的结果

Frame不变,修改了anchorPoint 对图层的影响

1、分析橙色Layer
在保持Frame不变的情况下,anchorPoint是(0, 0),位于layer的左上角,position也是位于layer的左上角,layer以左上角为定位点,此时positon的意义是 layer的左上角距离父layer的原点的位置是position.x,position.y ,对layer进行45°的旋转之后,如图Layer以左上角做了顺时针的45°旋转。

2、分析红色Layer
在保持Frame不变的情况下,anchorPoint是(1, 01),位于layer的右下角,position也是位于layer的右下角,layer以右下角为定位点,此时positon的意义是 layer的右下距离父layer的原点的位置是position.x,position.y ,对layer进行45°的旋转之后,如图Layer以右下角做了顺时针的45°旋转。

例子的代码如下:

    // 在Frame不变的情况下讨论anchorPoint对position的影响
    // 可以这么认为,position是因变量,anchorPoint是自变量
    // anchorPoint和position是一一对应的,是同一个点
    layer = [[CALayer alloc] init];
    layer.borderColor = [UIColor blueColor].CGColor;
    layer.borderWidth = 1;
    layer.anchorPoint = CGPointMake(1, 1);
    layer.frame = CGRectMake(100, 300, 100, 100);
    [self.view.layer addSublayer:layer];
    
    {
        CALayer* copylayer = [self cloneLayer:layer];
        copylayer.borderColor = [UIColor orangeColor].CGColor;
        [self.view.layer addSublayer:copylayer];
        
        // Frame不变,anchorPoint设置到右下角,positon位置也会变到右下角{150, 500}
        copylayer.anchorPoint = CGPointMake(1, 1);
        copylayer.frame = CGRectMake(100, 300, 100, 100);
        NSLog(@"layer.position = %@", NSStringFromCGPoint(copylayer.position));
        
        // 旋转
        copylayer.affineTransform = CGAffineTransformRotate(copylayer.affineTransform, M_PI_4);
    }
    
    {
        CALayer* copylayer = [self cloneLayer:layer];
        copylayer.borderColor = [UIColor orangeColor].CGColor;
        [self.view.layer addSublayer:copylayer];
        
        // Frame不变,anchorPoint设置到坐上角,positon位置也会变到坐上角{50, 400}
        copylayer.anchorPoint = CGPointMake(0, 0);
        copylayer.frame = CGRectMake(100, 300, 100, 100);
        NSLog(@"layer.position = %@", NSStringFromCGPoint(copylayer.position));
        
        // 旋转
        copylayer.affineTransform = CGAffineTransformRotate(copylayer.affineTransform, M_PI_4);
    }

anchorPoint 应用场景

例子来自于《ios核心动画高级技巧》书中国的 时钟表盘例子

例子可以在我的git上找到ClockFace

初始的时钟指针在表盘中的位置如下:

初始的时钟指针在表盘中的位置

// 秒针
layer frame:{{124, 77}, {8, 102}} anchorPoint:{0.5, 0.5} position:{128, 128}
// 分针
layer frame:{{118, 75}, {20, 106}} anchorPoint:{0.5, 0.5} position:{128, 128}
// 时针
 layer frame:{{113, 81}, {30, 94}} anchorPoint:{0.5, 0.5} position:{128, 128}

没有设置anchorPoint的指针走动效果:

没有设置anchorPoint的指针走动效果

根据以上的分析我们知道原因是默认的anchorPoint为{0.5, 0.5},也就是旋转中心是指针的中心点导致的效果如此,知道原因了修改也不难了,最简单的做法就是把anchorPoint设置为{0.5, 0.9}即可。

    //adjust anchor points
    self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
    self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
    self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);

对应的指针的layer变化:

// 秒针
layer frame:{{124, 36.2}, {8, 102}} anchorPoint:{0.5, 0.89} position:{128, 128}
// 分针
layer frame:{{118, 32.6}, {20, 106}} anchorPoint:{0.5, 0.8} position:{128, 128}
// 时针
layer frame:{{113, 43.4}, {30, 94}} anchorPoint:{0.5, 0.89} position:{128, 128}

效果如下:

设置anchorPoint的指针走动效果

总结

以上是Layer中anchorPoint属性的一些总结以及一个应用场景,如有不妥之处敬请指教。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,094评论 5 13
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,465评论 6 30
  • Core Animation其实是一个令人误解的命名。你可能认为它只是用来做动画的,但实际上它是从一个叫做Laye...
    小猫仔阅读 3,684评论 1 4
  • 转载:http://www.jianshu.com/p/32fcadd12108 每个UIView有一个伙伴称为l...
    F麦子阅读 6,157评论 0 13
  • 引言 相信初接触到CALayer的人都会遇到以下几个问题: 为什么修改anchorPoint会移动layer的位置...
    大头青年阅读 871评论 1 8