- 锯齿状图形绘制
CAShapeLayer :图形绘制层,CALAyer的子类,初始化时只需用CALayer的类方法layer。
CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath
来定义想要绘制的图形,最后CAShapeLayer
就自动渲染出来了。当然,你也可以用Core Graphics直接向原始的CALyer
的内容中绘制一个路径,相比直下,使用CAShapeLayer
有以下一些优点:
- 渲染快速。
CAShapeLayer
使用了硬件加速,绘制同一图形会比用Core Graphics快很多。 - 高效使用内存。一个
CAShapeLayer
不需要像普通CALayer
一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。 - 不会被图层边界剪裁掉。一个
CAShapeLayer
可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer
一样被剪裁掉。 - 不会出现像素化。当你给
CAShapeLayer
做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。
需要配置绘制线的颜色(strokeColor)、宽度(lineWidth)和填充颜色(fillColor)根据自己需求配置
CAShapeLayer需要知道自己沿着什么路径进行绘制,所以我们要给其设置路径path,path是CGPathRef类型。
使用UIBezierPath贝塞尔曲线绘制路径可以直接生成圆、矩形、椭圆等等,也可以根据自己需求进行划线形成路线。
由于CAShapeLayer的path属性是CGPathRef,所以我们赋值时是:layer.path = Path.CGPath;
建立如图锯齿图表步骤:
- 新建一个视图PDARCProgressView继承自UIView
- 重写- (void)drawRect:(CGRect)rect 方法进行绘图
- 当绘制图形时要考虑很多种情况例如:
当数据源为空的时候即没有任何数据时:
if (self.categoryArray.count == 0) {
UIBezierPath *Path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.f, self.frame.size.height / 2.f) radius:66 startAngle:- M_PI endAngle: + M_PI clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = Path.CGPath;
layer.fillColor = ColorWithHex(@"#cccccc").CGColor;
layer.strokeColor = kMainBorderColor.CGColor;
layer.lineWidth = 2;
[self.layer addSublayer:layer];
}
当数据源数量为1时:CGFloat beforeWith = 0;
CGFloat startAngle = - M_PI;
for (int i = 0; i < self.categoryArray.count; i ++) {
NSNumber *radius = @(0);
while (radius.floatValue == beforeWith) {
radius = [withArr objectAtIndex:arc4random()%3];
}
beforeWith = radius.floatValue;
UIBezierPath *Path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.f, self.frame.size.height / 2.f) radius:beforeWith startAngle:startAngle endAngle:startAngle + PDAngle((1.0 / self.categoryArray.count)) clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = Path.CGPath;
layer.fillColor = ((UIColor *)colors[i % 10]).CGColor;
layer.strokeColor = kMainBorderColor.CGColor;
layer.lineWidth = 2;
[self.layer addSublayer:layer];
然后是正常状态时:UIBezierPath *Path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.f, self.frame.size.height / 2.f) radius:66 startAngle:- M_PI endAngle: + M_PI clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = Path.CGPath;
layer.fillColor = ((UIColor *)colors[0]).CGColor;
layer.strokeColor = kMainBorderColor.CGColor;
layer.lineWidth = 2;
[self.layer addSublayer:layer];
源码地址: 图表绘制CGFloat beforeWith = 0;
CGFloat startAngle = - M_PI + M_PI_4;
CGFloat firstWith = -1;
for (int i = 0; i < self.categoryArray.count; i ++) {
DBMainSchoolModel *model = self.categoryArray[i];
NSNumber *radius = [withArr objectAtIndex:arc4random()%3];
if (i > 9) {
radius = withArr[2];
} else {
while (radius.floatValue == beforeWith) {
radius = [withArr objectAtIndex:arc4random()%3];
}
if (i == 0) {
firstWith = beforeWith;
}
}
beforeWith = radius.floatValue;
UIBezierPath *Path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2.f, self.frame.size.height / 2.f) radius:beforeWith startAngle:startAngle endAngle:startAngle + PDAngle(([model.course floatValue] / self.totla)) clockwise:YES];
startAngle += PDAngle(([model.course floatValue] / self.totla));
[Path addLineToPoint:CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0)];
[Path closePath];
if (startAngle > M_PI) {
startAngle -= 2 * M_PI;
}
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = Path.CGPath;
if (i > 9) {
layer.fillColor = ColorWithHex(@"#cccccc").CGColor;
} else {
layer.fillColor = ((UIColor *)colors[i % 10]).CGColor;
}
layer.strokeColor = kMainBorderColor.CGColor;
layer.lineWidth = 2;
[self.layer addSublayer:layer];
}