[iOS Animation]-CALayer 图层几何学

图层几何学

不熟悉几何学的人就不要来这里了 --柏拉图学院入口的签名 git

在第二章里面,咱们介绍了图层背后的图片,和一些控制图层坐标和旋转的属性。在这一章中,咱们将要看一看图层内部是如何根据父图层和兄弟图层来控制位置和尺寸的。另外咱们也会涉及如何管理图层的几何结构,以及它是如何被自动调整和自动布局影响的。 github

布局

UIView有三个比较重要的布局属性:frame,bounds和center,CALayer对应地叫作frame,bounds和position。为了能清楚区分,图层用了“position”,视图用了“center”,可是他们都表明一样的值。 布局

frame表明了图层的外部坐标(也就是在父图层上占据的空间),bounds是内部坐标({0, 0}一般是图层的左上角),center和position都表明了相对于父图层anchorPoint所在的位置。anchorPoint的属性将会在后续介绍到,如今把它想成图层的中心点就行了。图3.1显示了这些属性是如何相互依赖的。 ui

图3.1

图3.1 UIView和CALayer的坐标系 atom

视图的frame,bounds和center属性仅仅是存取方法,当操纵视图的frame,其实是在改变位于视图下方CALayer的frame,不可以独立于图层以外改变视图的frame。 spa

对于视图或者图层来讲,frame并非一个很是清晰的属性,它实际上是一个虚拟属性,是根据bounds,position和transform计算而来,因此当其中任何一个值发生改变,frame都会变化。相反,改变frame的值一样会影响到他们当中的值 指针

记住当对图层作变换的时候,好比旋转或者缩放,frame实际上表明了覆盖在图层旋转以后的整个轴对齐的矩形区域,也就是说frame的宽高可能和bounds的宽高再也不一致了(图3.2) component

图3.2

图3.2 旋转一个视图或者图层以后的frame属性 orm

锚点

以前提到过,视图的center属性和图层的position属性都指定了anchorPoint相对于父图层的位置。图层的anchorPoint经过position来控制它的frame的位置,你能够认为anchorPoint是用来移动图层的把柄接口

默认来讲,anchorPoint位于图层的中点,因此图层的将会以这个点为中心放置。anchorPoint属性并无被UIView接口暴露出来,这也是视图的position属性被叫作“center”的缘由。可是图层的anchorPoint能够被移动,好比你能够把它置于图层frame的左上角,因而图层的内容将会向右下角的position方向移动(图3.3),而不是居中了。

图3.3

图3.3 改变anchorPoint的效果

和第二章提到的contentsRect和contentsCenter属性相似,anchorPoint用单位坐标来描述,也就是图层的相对坐标,图层左上角是{0, 0},右下角是{1, 1},所以默认坐标是{0.5, 0.5}。anchorPoint能够经过指定x和y值小于0或者大于1,使它放置在图层范围以外。

注意在图3.3中,当改变了anchorPoint,position属性保持固定的值并无发生改变,可是frame却移动了。

那在什么场合须要改变anchorPoint呢?既然咱们能够随意改变图层位置,那改变anchorPoint不会形成困惑么?为了举例说明,咱们来举一个实用的例子,建立一个模拟闹钟的项目。

钟面和钟表由四张图片组成(图3.4),为了简单说明,咱们仍是用传统的方式来装载和加载图片,使用四个UIImageView实例(固然你也能够用正常的视图,设置他们图层的contents图片)。

图3.4

图3.4 组成钟面和钟表的四张图片

闹钟的组件经过IB来排列(图3.5),这些图片视图嵌套在一个容器视图以内,而且自动调整和自动布局都被禁用了。这是由于自动调整会影响到视图的frame,而根据图3.2的演示,当视图旋转的时候,frame是会发生改变的,这将会致使一些布局上的失灵。

咱们用NSTimer来更新闹钟,使用视图的transform属性来旋转钟表(若是你对这个属性不太熟悉,不要着急,咱们将会在第5章“变换”当中详细说明),具体代码见清单3.1

图3.5

图3.5 在Interface Builder中布局闹钟视图

清单3.1 Clock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@interface ViewController ()
 
@property (nonatomic, weak) IBOutlet UIImageView *hourHand;
@property (nonatomic, weak) IBOutlet UIImageView *minuteHand;
@property (nonatomic, weak) IBOutlet UIImageView *secondHand;
@property (nonatomic, weak) NSTimer *timer;
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    //start timer
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(tick) userInfo:nil repeats:YES];
                  
    //set initial hand positions
    [self tick];
}
 
- (void)tick
{
    //convert time to hours, minutes and seconds
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
    CGFloat hoursAngle = (components.hour / 12.0) * M_PI * 2.0;
    //calculate hour hand angle //calculate minute hand angle
    CGFloat minsAngle = (components.minute / 60.0) * M_PI * 2.0;
    //calculate second hand angle
    CGFloat secsAngle = (components.second / 60.0) * M_PI * 2.0;
    //rotate hands
    self.hourHand.transform = CGAffineTransformMakeRotation(hoursAngle);
    self.minuteHand.transform = CGAffineTransformMakeRotation(minsAngle);
    self.secondHand.transform = CGAffineTransformMakeRotation(secsAngle);
}
 
@end

运行项目,看起来有点奇怪(图3.6),由于钟表的图片在围绕着中心旋转,这并非咱们期待的一个支点。

图3.6

图3.6 钟面,和不对齐的钟指针

你也许会认为能够在Interface Builder当中调整指针图片的位置来解决,但其实并不能达到目的,由于若是不放在钟面中间的话,一样不能正确的旋转。

也许在图片末尾添加一个透明空间也是个解决方案,但这样会让图片变大,也会消耗更多的内存,这样并不优雅。

更好的方案是使用anchorPoint属性,咱们来在-viewDidLoad方法中添加几行代码来给每一个钟指针的anchorPoint作一些平移(清单3.2),图3.7显示了正确的结果。

清单3.2

1
2
3
4
5
6
7
8
9
10
11
12
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 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);
 
 
    // start timer
}

图3.7

图3.7 钟面,和正确对齐的钟指针

相关文章
相关标签/搜索