一、CAShapeLayer的作用和优点
可以通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath
来定义想要绘制的图形
你也可以用Core Graphics直接向原始的CALyer
的内容中绘制一个路径,相比直下,使用CAShapeLayer
有以下一些优点:
- 渲染快速。
CAShapeLayer
使用了硬件加速,绘制同一图形会比用Core Graphics快很多。 - 高效使用内存。一个
CAShapeLayer
不需要像普通CALayer
一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。 - 不会被图层边界剪裁掉。一个
CAShapeLayer
可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer
一样被剪裁掉(如我们在第二章所见)。 - 不会出现像素化。当你给
CAShapeLayer
做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。
二、实际例子
三、上面的例子是二维码扫描界面,界面中需要一个中间透明的提示框,以及四个直角的标记,可以通过CASharpLayer来实现
中间的透明可以通过UIview的maskLayer来进行掩码实现
四个角的黄线通过CASharpLayer来实现
- (void)addOverlay
{
//innerrect就是中空的frame
CGRect innerRect = [self getInnerRect];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:innerRect
cornerRadius:0];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.5;
[self.layer addSublayer:fillLayer];
_maskLayer = fillLayer;
_overlay = [[CAShapeLayer alloc] init];
_overlay.backgroundColor = [UIColor clearColor].CGColor;
_overlay.fillColor = [UIColor clearColor].CGColor;
_overlay.strokeColor = [UIColor yellowColor].CGColor;
_overlay.lineWidth = 3;
innerRect = CGRectInset(innerRect, -_overlay.lineWidth/2, -_overlay.lineWidth/2);
CGFloat lineLength = 20;
UIBezierPath *cornerPath = [UIBezierPath bezierPath];
//left-top corner
CGPoint leftTop = CGPointMake(innerRect.origin.x, innerRect.origin.y);
[cornerPath moveToPoint:CGPointMake(leftTop.x, leftTop.y + lineLength)];
[cornerPath addLineToPoint:leftTop];
[cornerPath addLineToPoint:CGPointMake(leftTop.x + lineLength, leftTop.y)];
//right-top corner
CGPoint rightTop = CGPointMake(innerRect.origin.x + innerRect.size.width, innerRect.origin.y);
[cornerPath moveToPoint:CGPointMake(rightTop.x - lineLength, rightTop.y)];
[cornerPath addLineToPoint:rightTop];
[cornerPath addLineToPoint:CGPointMake(rightTop.x, rightTop.y + lineLength)];
//right-bottom corner
CGPoint rightBottom = CGPointMake(innerRect.origin.x + innerRect.size.width,
innerRect.origin.y + innerRect.size.height);
[cornerPath moveToPoint:CGPointMake(rightBottom.x, rightBottom.y - lineLength)];
[cornerPath addLineToPoint:rightBottom];
[cornerPath addLineToPoint:CGPointMake(rightBottom.x - lineLength, rightBottom.y)];
//left-bottom corner
CGPoint leftBottom = CGPointMake(innerRect.origin.x,
innerRect.origin.y + innerRect.size.height);
[cornerPath moveToPoint:CGPointMake(leftBottom.x + lineLength, leftBottom.y)];
[cornerPath addLineToPoint:leftBottom];
[cornerPath addLineToPoint:CGPointMake(leftBottom.x, leftBottom.y - lineLength)];
_overlay.path = cornerPath.CGPath;
[self.layer addSublayer:_overlay];
}