锯齿状图表绘制

时间:2023-02-10 12:13:17
锯齿状图表绘制
  • 锯齿状图形绘制

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;

锯齿状图表绘制

建立如图锯齿图表步骤:

  1. 新建一个视图PDARCProgressView继承自UIView
  2. 重写- (void)drawRect:(CGRect)rect 方法进行绘图
  3. 当绘制图形时要考虑很多种情况例如:

当数据源为空的时候即没有任何数据时:

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];
}

当数据源所有数据得分都是0时:

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];

当数据源数量为1时:

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];
}

源码地址: 图表绘制