iOS绘制折线统计图

1.折线统计图的绘制分析

       折线统计图主要由x轴,y轴以及连接起来的虚线,绘制的点组成。

2.折线统计图的绘制 

       这里我主要是用CAShapeLayer 和 UIBezierPath 去绘制。

       第一步先绘制x轴和y轴。

- (void)drawXAxisLine {
    CAShapeLayer *layer = [CAShapeLayer layer];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, self.drawLineScrollView.height - BOTTOM_HEIGHT)];
    [path addLineToPoint:CGPointMake(_xEveryWidth * (_statisticalModel.xTitleArray.count - 1), self.drawLineScrollView.height - BOTTOM_HEIGHT)];
    
    layer.frame = CGRectMake(0, 0, self.drawLineScrollView.contentSize.width, self.drawLineScrollView.contentSize.height - BOTTOM_HEIGHT);
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor grayColor].CGColor;
    layer.lineWidth = 1;
    layer.fillColor = nil;
    [self.drawLineScrollView.layer addSublayer:layer];
    
    for (int i = 0; i < _statisticalModel.xTitleArray.count; i ++) {
        UILabel *label = [[UILabel alloc] init];
        label.font = [UIFont systemFontOfSize:12];
        label.textColor = [UIColor blackColor];
        label.textAlignment = NSTextAlignmentCenter;
        label.text = _statisticalModel.xTitleArray[i];
        [label sizeToFit];
        if (i == 0) {
            label.x = [_xAxisPointArray[i] CGPointValue].x;
        }else {
           label.x = [_xAxisPointArray[i] CGPointValue].x - label.width / 2;
        }
        
        label.y = [_xAxisPointArray[i] CGPointValue].y + label.height / 2;
        [self.drawLineScrollView addSubview:label];
    }
}
- (void)drawYAxisLine {
    
    CAShapeLayer *layer = [CAShapeLayer layer];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(LEFT_MARGIN, self.height - BOTTOM_HEIGHT)];
    [path addLineToPoint:CGPointMake(LEFT_MARGIN, 0)];
    layer.frame = CGRectMake(0, 0, self.width, self.height - BOTTOM_HEIGHT);
    layer.path = path.CGPath;
    layer.strokeColor = [UIColor grayColor].CGColor;
    layer.lineWidth = 1;
    layer.fillColor = nil;
    [self.layer addSublayer:layer];
    
    for (int i = 0; i < _statisticalModel.yTitleArray.count; i ++) {
        UILabel *label = [[UILabel alloc] init];
        label.font = [UIFont systemFontOfSize:12];
        label.textColor = [UIColor blackColor];
        label.textAlignment = NSTextAlignmentCenter;
        label.text = _statisticalModel.yTitleArray[i];
        [label sizeToFit];
        label.x = [_yAxisPointArray[i] CGPointValue].x - label.width + LEFT_MARGIN - RIGHT_MARGIN / 4;
        label.y = [_yAxisPointArray[i] CGPointValue].y - label.height / 2 - RIGHT_MARGIN / 5;
        [self addSubview:label];
    }
}

     第二步,绘制虚线,将每个点连接起来

- (void)drawDottedLine {
    CAShapeLayer *layer = [CAShapeLayer layer];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    for (int i = 0; i < _statisticalModel.yTitleArray.count; i ++) {
        for (int j = 0; j < _statisticalModel.xTitleArray.count; j ++) {
            [path moveToPoint:CGPointMake(0,i * _yEveryHeight)];
            [path addLineToPoint:CGPointMake((_statisticalModel.xTitleArray.count - 1) * _xEveryWidth, i * _yEveryHeight)];
            
            [path moveToPoint:CGPointMake(j * _xEveryWidth,self.height - BOTTOM_HEIGHT)];
            [path addLineToPoint:CGPointMake(j * _xEveryWidth, 0)];
        }
    }
    
    layer.frame = CGRectMake(0, 0, self.drawLineScrollView.contentSize.width, self.drawLineScrollView.contentSize.height);
    layer.path = path.CGPath;
    layer.strokeColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5].CGColor;
    layer.lineWidth = 0.5;
    layer.lineDashPattern = @[@5,@5];
    layer.fillColor = nil;
    [self.drawLineScrollView.layer addSublayer:layer];
}

        第三步,也是最为重要的转换坐标,计算单位1长度。根据所要描绘的点,首先拿到x轴和y轴的最大最小值,然后再计算每个点在坐标系中的位置,在iOS中,起点为(0,0)的点在视图的左上角,在坐标系中起点(0,0)在视图的左下角,所以这里要注意转换一下。

- (void)changePoint {

    for (int i = 0; i < self.statisticalModel.pointArray.count; i ++) {
        
        NSArray *pointArray = self.statisticalModel.pointArray[i];
        
        CGFloat maxX = -MAXFLOAT;
        CGFloat minX = MAXFLOAT;
        CGFloat maxY = -MAXFLOAT;
        CGFloat minY = MAXFLOAT;
        
        // 转换坐标
        NSMutableArray *pointMutArray = [NSMutableArray arrayWithCapacity:pointArray.count];
        
        for (NSValue *value in pointArray) {
            CGPoint point = [value CGPointValue];
            
            if (point.x > maxX) {
                maxX = point.x;
            }
            
            if (point.x < minX) {
                minX = point.x;
            }
            
            if (point.y > maxY) {
                maxY = point.y;
            }
            
            if (point.y < minY) {
                minY = point.y;
            }
            
            CGFloat xUnitLong = [self getNumber:((maxX - minX) / (CGFloat)_statisticalModel.xTitleArray.count)];
            CGFloat yUnitLong = [self getNumber:(maxY - minY) / (CGFloat)_statisticalModel.yTitleArray.count];
            
            point.y = [self getNumber:self.height - BOTTOM_HEIGHT - point.y * yUnitLong * _yEveryHeight];
            
            point.x = [self getNumber:point.x * xUnitLong * _xEveryWidth];
            
            [pointMutArray addObject:[NSValue valueWithCGPoint:point]];
        }
        
        [self drawLineWithPointArray:pointMutArray withIndex:i];
    }
}

第四部就是去画线。
 

- (void)drawLineWithPointArray:(NSArray *)pointArray withIndex:(NSInteger)index {
    // 绘制
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:[pointArray[0] CGPointValue]];
    
    for (int i = 1; i < pointArray.count; i ++) {
        [path addLineToPoint:[pointArray[i] CGPointValue]];
    }

    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame = CGRectMake(0, 0, self.drawLineScrollView.contentSize.width, self.drawLineScrollView.contentSize.height);
    layer.path = path.CGPath;
    layer.strokeColor = (__bridge CGColorRef _Nullable)(self.statisticalModel.lineColors[index]);
    layer.lineWidth = [self.statisticalModel.lineWidths[index] floatValue];
    layer.fillColor = [UIColor clearColor].CGColor;
    [self.drawLineScrollView.layer addSublayer:layer];
    
    if (self.statisticalModel.colors.count > 0) {
        [self fillColorWithPointArray:pointArray withIndex:index];
    }
}

这里还有个方法就是填充颜色。

- (void)fillColorWithPointArray:(NSArray *)pointArray withIndex:(NSInteger)index {
    // 绘制
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:[pointArray[0] CGPointValue]];
    
    for (int i = 1; i < pointArray.count; i ++) {
        [path addLineToPoint:[pointArray[i] CGPointValue]];
    }
    
    [path addLineToPoint:CGPointMake([pointArray.lastObject CGPointValue].x, self.drawLineScrollView.height - BOTTOM_HEIGHT)];
    
    CAGradientLayer *gradientaLayer = [CAGradientLayer layer];
    gradientaLayer.frame = CGRectMake(0, 0, self.drawLineScrollView.contentSize.width, self.drawLineScrollView.height - BOTTOM_HEIGHT);
    gradientaLayer.locations = @[@0.5];
    gradientaLayer.startPoint = CGPointMake(0, 0);
    gradientaLayer.endPoint = CGPointMake(1, 0);
    
    gradientaLayer.colors = self.statisticalModel.colors[index];

    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.frame = CGRectMake(0, 0, self.drawLineScrollView.contentSize.width, self.drawLineScrollView.contentSize.height);
    layer.path = path.CGPath;
    gradientaLayer.mask = layer;
    [self.drawLineScrollView.layer addSublayer:gradientaLayer];
}

核心的思路大概就是这些,具体想要看demo的同学请点击上方下载。

绘制效果如下:

下载地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值