iOS數據統計(柱狀圖、折線圖、扇形圖)

大數據(big data),指無法在一定時間範圍內用常規軟件工具進行捕捉、管理和處理的數據集合,是需要新處理模式才能具有更強的決策力、洞察發現力和流程優化能力的海量、高增長率和多樣化的信息資產。
大數據技術的戰略意義不在於掌握龐大的數據信息,而在於對這些含有意義的數據進行專業化處理。換而言之,如果把大數據比作一種產業,那麼這種產業實現盈利的關鍵,在於提高對數據的“加工能力”,通過“加工”實現數據的“增值”。

前言

今年大數據行業火爆異常,大數據的實用點之一在於數據的統計和加工實現數據的“增值”,方便人們從大量的數據統計中得出結論。

對於一個iOS開發程序猿來說不是專門搞大數據開發的,似乎沒有多大關係,但後續iOS開發中,各類APP中必然會加入統計表格的形式展示數據,相對於傳統的列表形式+各類查詢顯示,表格形式直觀、簡潔、通俗易懂,分析更透徹,必然會成爲搶手貨。

本文介紹一下簡易的柱狀圖、折線圖、扇形圖三種統計圖的製作,希望能幫助到大家

座標系

利用CAShapeLayer和UIBezierPath繪製座標系,座標系中需要繪製的部分如下圖所示:
座標軸
需要繪製的部分有原點、x座標軸、y座標軸、座標軸末尾的箭頭和座標軸上的標度。需要計算位置和長度,需要根據所在頁面的大小計算座標系的位置和大小。

這裏給出代碼如下:

    CAShapeLayer *layer = [CAShapeLayer layer];
    UIBezierPath *path = [UIBezierPath bezierPath];
    //座標軸原點
    CGPoint rPoint = CGPointMake(1.3*margin, self.zzHeight-margin);
    //畫y軸
    [path moveToPoint:rPoint];
    [path addLineToPoint:CGPointMake(1.3*margin, margin)];
    //畫y軸的箭頭
    [path moveToPoint:CGPointMake(1.3*margin, margin)];
    [path addLineToPoint:CGPointMake(1.3*margin-5, margin+5)];
    [path moveToPoint:CGPointMake(1.3*margin, margin)];
    [path addLineToPoint:CGPointMake(1.3*margin+5, margin+5)];
    //畫x軸
    [path moveToPoint:rPoint];
    [path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin, self.zzHeight-margin)];
    //畫x軸的箭頭
    [path moveToPoint:CGPointMake(self.zzWidth-0.8*margin, self.zzHeight-margin)];
    [path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin-5, self.zzHeight-margin-5)];
    [path moveToPoint:CGPointMake(self.zzWidth-0.8*margin, self.zzHeight-margin)];
    [path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin-5, self.zzHeight-margin+5)];
    //畫x軸上的標度
    for (int i=0; i<x_itemArr.count; i++) {
        [path moveToPoint:CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1), self.zzHeight-margin)];
        [path addLineToPoint:CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1), self.zzHeight-margin-3)];
    }
    //畫y軸上的標度
    for (int i=0; i<10; i++) {
        [path moveToPoint:CGPointMake(1.3*margin, margin+(self.zzHeight-2*margin)/11*(i+1))];
        [path addLineToPoint:CGPointMake(1.3*margin+3, margin+(self.zzHeight-2*margin)/11*(i+1))];
    }
    layer.path = path.CGPath;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.strokeColor = [UIColor blackColor].CGColor;
    layer.lineWidth = 2.0;
    [self.layer addSublayer:layer];
    //給y軸加標註
    for (int i=0; i<11; i++) {
        CGFloat yLHeight = (self.zzHeight-2*margin)/11 <= 20 ? (self.zzHeight-2*margin)/11 : 20;
        CGFloat yLWidth = yLHeight*2 >= 25 ? 25 : yLHeight*2;
        CGFloat size = (self.zzHeight-2*margin)/11 <= 20 ? 7 : 12;
        UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(1.3*margin-yLWidth-5, margin+(self.zzHeight-2*margin)/11*(10-i+0.5), yLWidth, yLHeight)];
        lab.text = [NSString stringWithFormat:@"%d", 10*i];
        lab.textColor = [UIColor blackColor];
        lab.font = [UIFont boldSystemFontOfSize:size];
        lab.textAlignment = NSTextAlignmentCenter;
        [self addSubview:lab];
    }

柱狀圖

在繪製座標系的基礎上,繪製柱狀圖的原理非常簡單,根據x軸的座標,計算每條柱的高度。

這裏需要注意:
提供的數據需要轉化爲自己設定的y軸的刻度單位計算出的高度。另外,柱狀圖需要佔用x軸的寬度,所以柱子的位置需要好好考慮一下放在x軸的什麼位置。

代碼如下:

    //畫柱狀圖
    for (int i=0; i<x_itemArr.count; i++) {
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+0.7),     self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10,      0.6*((self.zzWidth-2*margin)/(x_itemArr.count+1)),     (self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10-1)];
        CAShapeLayer *layer = [CAShapeLayer layer];
        layer.path = path.CGPath;
        layer.fillColor = zzRandomColor.CGColor;
        layer.strokeColor = [UIColor clearColor].CGColor;
        [self.layer addSublayer:layer];
    }
    //給x軸加標註
    for (int i=0; i<x_itemArr.count; i++) {
        CGFloat xLWidth = ((self.zzWidth-2*margin)/(x_itemArr.count+1)) <= 25 ? ((self.zzWidth-2*margin)/(x_itemArr.count+1)) : 25;
        UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1)-xLWidth/2, self.zzHeight-margin, xLWidth, 20)];
        lab.text = x_itemArr[i];
        lab.textColor = [UIColor blackColor];
        lab.adjustsFontSizeToFitWidth = YES;
        lab.textAlignment = NSTextAlignmentCenter;
        [self addSubview:lab];
    }

效果如下:
柱狀圖

折線圖

在座標系的基礎上,計算繪製對應y軸上的點,然後從第一個點開始,依次連接到最後一個點,可以直線連接,或者用貝塞爾曲線繪製,具體看實際情況實現。

代碼如下:

    //開始點
    CGPoint startPoint = CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1), self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[0] floatValue]/10);
    //結束點
    CGPoint endPoint;
    for (int i=0; i<x_itemArr.count; i++) {
        endPoint = CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1), self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10);
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:startPoint];
        [path addArcWithCenter:endPoint radius:1.5 startAngle:0 endAngle:2*M_PI clockwise:YES];
        [path addLineToPoint:endPoint];
        //繪製連線
        CAShapeLayer *layer = [CAShapeLayer layer];
        layer.path = path.CGPath;
        layer.strokeColor = [UIColor redColor].CGColor;
        layer.lineWidth = 1.0;
        [self.layer addSublayer:layer];
        //繪製點
        CAShapeLayer *layer1 = [CAShapeLayer layer];
        layer1.frame = CGRectMake(endPoint.x-2, endPoint.y-2, 4, 4);
        layer1.backgroundColor = [UIColor blackColor].CGColor;
        [self.layer addSublayer:layer1];
        //繪製虛線
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    [shapeLayer setStrokeColor:[UIColor blackColor].CGColor];
    [shapeLayer setLineWidth:1];
    [shapeLayer setLineJoin:kCALineJoinRound];
    //設置虛線的線寬及間距
    [shapeLayer setLineDashPattern:[NSArray arrayWithObjects:[NSNumber numberWithInt:2], [NSNumber numberWithInt:3], nil]];
    //創建虛線繪製路徑
    CGMutablePathRef path = CGPathCreateMutable();
    //設置y軸方向的虛線
    CGPathMoveToPoint(path, NULL, point.x, point.y);
    CGPathAddLineToPoint(path, NULL, point.x, self.zzHeight-margin);
    //設置x軸方向的虛線
    CGPathMoveToPoint(path, NULL, point.x, point.y);
    CGPathAddLineToPoint(path, NULL, 1.3*margin, point.y);
    //設置虛線繪製路徑
    [shapeLayer setPath:path];
    CGPathRelease(path);
    [self.layer addSublayer:shapeLayer];
        startPoint = endPoint;
    }
    //給x軸加標註
    for (int i=0; i<x_itemArr.count; i++) {
        CGFloat xLWidth = ((self.zzWidth-2*margin)/(x_itemArr.count+1)) <= 25 ? ((self.zzWidth-2*margin)/(x_itemArr.count+1)) : 25;
        UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1)-xLWidth/2, self.zzHeight-margin, xLWidth, 20)];
        lab.text = x_itemArr[i];
        lab.textColor = [UIColor blackColor];
        lab.adjustsFontSizeToFitWidth = YES;
        lab.textAlignment = NSTextAlignmentCenter;
        [self addSubview:lab];
    }

效果圖如下:
折線圖

扇形圖

扇形圖製作需要首先計算每一條數據佔數據總和的百分比,然後以頁面中心點爲中心,指定半徑,開始畫扇形,每條數據對應一個扇形,起點半徑每次都不一樣,知道最後一條數據畫完,可以正好得到一個整圓。

代碼如下:

CGPoint yPoint = CGPointMake(self.zzWidth/2, self.zzHeight/2);
    CGFloat startAngle = 0;
    CGFloat endAngle;
    float r = self.zzHeight/3;
    //求和
    float sum=0;
    for (NSString *str in y_itemArr) {
        sum += [str floatValue];
    }
    for (int i=0; i<x_itemArr.count; i++) {
        //求每一個的佔比
        float zhanbi = [y_itemArr[i] floatValue]/sum;
        endAngle = startAngle + zhanbi*2*M_PI;
        CAShapeLayer *layer = [CAShapeLayer layer];
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:yPoint radius:r startAngle:startAngle endAngle:endAngle clockwise:YES];
        [path addLineToPoint:yPoint];
        [path closePath];
        CGFloat bLWidth = self.zzHeight/6+5 >= 45 ? 40 : self.zzHeight/6;
        CGFloat size = self.zzHeight/6+5 >= 45 ? 9 : 5;
        CGFloat lab_x = yPoint.x + (r + bLWidth/2) * cos((startAngle + (endAngle - startAngle)/2)) - bLWidth/2;
        CGFloat lab_y = yPoint.y + (r + bLWidth*3/8) * sin((startAngle + (endAngle - startAngle)/2)) - bLWidth*3/8;
        UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(lab_x, lab_y, bLWidth, bLWidth*3/4)];
        lab.text = [NSString stringWithFormat:@"%@\n%.2f%@",x_itemArr[i],zhanbi*100,@"%"];
        lab.textColor = [UIColor blackColor];
        lab.numberOfLines = 0;
        lab.font = [UIFont boldSystemFontOfSize:size];
        lab.textAlignment = NSTextAlignmentCenter;
        [self addSubview:lab];
        layer.path = path.CGPath;
        layer.fillColor = zzRandomColor.CGColor;
        layer.strokeColor = [UIColor clearColor].CGColor;
        [self.layer addSublayer:layer];
        startAngle = endAngle;
    }

效果圖如下:
扇形圖

尾聲

簡易的三種畫法,僅用於展示數據,封裝類和Demo已經上傳到了GitHub上,地址:https://github.com/fuzheng0301/DrawChart,感謝star,希望能給大家帶來幫助,也希望能看到大神的更精彩的分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章