- - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
- {
- CGFloat width = 10.0f;
-
-
- CGContextSetLineWidth(ctx, width);
- CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
-
- CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
-
- CGContextStrokeEllipseInRect(ctx, rect);
- }
接上次,修改了一下,呵呵,看着舒服多了xcode

因而可知线宽的扩展方式是同时向两边扩展的。app
第三章:Layer Geometryless
“Let no one unversed in geometry enter here.”
看到做者的信心了吧,你有了吗?函数
UIView的布局属性有frame,bounds和center,CALayer一样有3个对应frame,bounds和position。如图:oop

须要注意的是,frame不是一个独立的属性,它是由bounds,position,transform等其余属性计算而来,因此改变frame会影响其余属性,反之改变其余属性也会影响frame。若是我在前面的例子里增长一行改变frame的代码你会看到以下结果布局
- - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
- {
- CGFloat width = 10.0f;
-
-
- CGContextSetLineWidth(ctx, width);
- CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
-
- CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
-
- CGContextStrokeEllipseInRect(ctx, rect);
-
- layer.frame = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
- }

还有须要注意在操做transform时,如旋转时,frame会从新计算,此时frame的宽高再也不和bounds比配。如图学习

下面再说说anchorPoint这个属性,不少人对于使用此属性可能会迷惑,究竟是怎么设置的,先看张图this

anchorPoint从{0.5, 0.5}变为{0, 0},layer向右下偏移了,下面你们能够用一下作个试验atom
仍是使用上面的例子,在- (void)viewDidLoad的[blueLayerdisplay];前增长spa
- NSLog(@"%@", NSStringFromCGPoint(blueLayer.anchorPoint));
- NSLog(@"%@", NSStringFromCGPoint(blueLayer.position));
是为了记录变化前的值,接着在- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx中
增长对anchorPoint的设置,自已能够任意设置看看结果
- - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
- {
- CGFloat width = 10.0f;
-
-
- CGContextSetLineWidth(ctx, width);
- CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
-
- CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
-
- CGContextStrokeEllipseInRect(ctx, rect);
- layer.anchorPoint = CGPointMake(0, 0);
- NSLog(@"%@", NSStringFromCGPoint(layer.position));
- }
咱们能够得出结论,anchorPoint能够简单地看做是设置左上顶点相对于中心position的位置,
计数以左上顶点到position的距离与宽高的比例,X轴方向正为左移负为右移,Y轴方向正为上移负为下移。
下面咱们用例子来看看具体的应用,具体代码请查看例子3.1
源码在这里下载:http://www.informit.com/title/9780133440751
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
-
- self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
- target:self
- selector:@selector(tick)
- userInfo:nil
- repeats:YES];
-
-
- [self tick];
- }
-
- - (void)tick
- {
-
- NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
- NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
- NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
-
-
- CGFloat hourAngle = (components.hour / 12.0) * M_PI * 2.0;
-
-
- CGFloat minuteAngle = (components.minute / 60.0) * M_PI * 2.0;
-
-
- CGFloat secondAngle = (components.second / 60.0) * M_PI * 2.0;
-
-
- self.hourHand.transform = CGAffineTransformMakeRotation(hourAngle);
- self.minuteHand.transform = CGAffineTransformMakeRotation(minuteAngle);
- self.secondHand.transform = CGAffineTransformMakeRotation(secondAngle);
- }

运行看看结果

发现什么了没有?CGAffineTransformMakeRotation以View的center点在旋转
再看例子3.2,修改代码
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
-
- 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);
-
-
- self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
- target:self
- selector:@selector(tick)
- userInfo:nil
- repeats:YES];
-
-
- [self tick];
- }
看结果

CGAffineTransformMakeRotation以layer的position点在旋转
相对坐标的转换函数,UIView使用:
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;
CALayer使用:
- (CGPoint)convertPoint:(CGPoint)p fromLayer:(CALayer *)l;
- (CGPoint)convertPoint:(CGPoint)p toLayer:(CALayer *)l;
- (CGRect)convertRect:(CGRect)r fromLayer:(CALayer *)l;
- (CGRect)convertRect:(CGRect)r toLayer:(CALayer *)l;
注意:直到OS X 10.8才出现了geometryFlipped属性,该属性能够改变默认图层y坐标的方向。当翻转变换被调用时,使用该属性来调整图层的方向有的时候是必需的。若是父视图使用了翻转变换,它的子视图内容(以及它对应的图层)将常常被颠倒。在这种状况下,设置子图层的geometryFlipped属性为YES是一种修正该问题最简单的方法。在OS X 10.8及以上版本,AppKit负责管理该属性,你不该该更改它。对于iOS app,不推荐使用geometryFlipped属性。

“This is a BOOL value that determines whether the geometry of a layer is vertically flipped with respect to its superlayer. Setting this property to YES for a layer on iOS means that its sublayers will be flipped vertically and will be positioned relative to the bottom of its bounds rather than the top as normal (as will all of their sublayers, and so on, unless they also have YES for their geometryFlipped property).”
注意的是geometryFlipped只对sublayers起做用,只到有sub也设置了YES才恢复,有点负负得正的意思
修改例子3.2代码
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
-
- self.view.layer.geometryFlipped = YES;
- 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);
-
-
- self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
- target:self
- selector:@selector(tick)
- userInfo:nil
- repeats:YES];
-
-
- [self tick];
- }

本身运行看看,指针反着转了。
再修改看看的geometryFlipped sublayers的做用域,呵呵暂且这么说
首先增长一个view做为secondHand的父view,修改代码

增长
- @property (weak, nonatomic) IBOutlet UIView *sView;
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
-
- self.view.layer.geometryFlipped = YES;
- self.sView.layer.geometryFlipped = YES;
- 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);
-
-
- self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
- target:self
- selector:@selector(tick)
- userInfo:nil
- repeats:YES];
-
-
- [self tick];
- }
看结果

秒针正常了
咱们之前接触的UIView是2维坐标,但如今CAlayer确实3维坐标,增长了Z轴, zPosition 和 anchorPointZ
看例子3.3,zPosition默认值为0,当设置self.greenView.layer.zPosition大于0时,greenView将遮盖redView

运行结果

例子3.4和3.5是对
- - (CALayer *)hitTest:(CGPoint)p;
-
- - (BOOL)containsPoint:(CGPoint)p;
两个函数的,本身去看