iOS 繪圖 - 如何繪製一個多邊形能力分佈圖

能力分佈圖

本文首發於:個人簡書javascript

#前言java

能力分佈圖是一個統計類常常須要的一個需求,須要必定的幾何計算,實現難度適中,在平時也很適合拿來用做iOS繪圖練手。
這裏寫了一個具備必定可複用行比較高的多邊形能力分佈圖,有須要的同窗能夠拿去用,也能夠當作本身的練手Demo。相關代碼我都放在個人Github-AWPolygonView上,後續會有優化更新,有什麼問題歡迎你們提出想法,互相學習進步。git

正文

1、計算各個點的座標

畫圖一個核心步驟是計算須要的點的座標。須要的點的類型爲:中心點、邊上的角、能力值的各個點。接下來開始計算各個點的座標。github

一、中心的點

x座標就是View的寬度的一半
y座標就是View的高度的一半ide

_centerX = self.bounds.size.width/2;
    _centerY = self.bounds.size.height/2;複製代碼
二、邊上的角度

根據須要是幾邊形,經過在一個以View的中心點爲圓心,view的寬度爲直徑的圓上取點。
而後經過角度和半徑 進行計算得到各個點的座標
cossin方法參數須要爲弧度,將其轉換成傳入參數爲角度的ANGLE_COS方法
公式爲:學習

1弧度=180/π度
1度=π/180弧度複製代碼

代碼就是:優化

#define ANGLE_COS(Angle) cos(M_PI / 180 * (Angle))
#define ANGLE_SIN(Angle) sin(M_PI / 180 * (Angle))複製代碼

接着經過一個循環計算每一個點的座標。
點的座標計算代碼以下:動畫

//self.radius 爲半徑
//self.sideNum爲總共多少個邊
//i爲逆時針第i個點

CGPoint cornerPoint = CGPointMake(
_centerX - ANGLE_COS(90.0 - 360.0 /self.sideNum * i) * self.radius,
_centerY - ANGLE_SIN(90.0 - 360.0 /self.sideNum * i) * self.radius);複製代碼
三、能力值點的座標

能力值的點不想邊上的點那麼有規律,半徑長短不一,可是角度跟邊上的點的角度是同樣的,因此只要在邊上的點的基礎上乘上半徑長短比例就能夠了。
代碼以下:spa

//Values
    for (int i = 0; i < self.sideNum; i++) {
        if (self.values.count > i) {
            CGFloat valueRadius = [self.values[i] floatValue] * self.radius;
            CGPoint valuePoint =  CGPointMake(_centerX - ANGLE_COS(90.0 - 360.0 /self.sideNum * i) * valueRadius,
                                              _centerY - ANGLE_SIN(90.0 - 360.0 /self.sideNum * i) * valueRadius);
            [tempValuePoints addObject:[NSValue valueWithCGPoint:valuePoint]];
        }
    }複製代碼

2、進行連線

一、採用CoreGraphics方法

各個點的座標肯定好了,接下來就是連線了,能夠採用CoreGraphics中的context繪製直線方法:code

CGContextMoveToPoint(CGContextRef  _Nullable c, CGFloat x, CGFloat y)
    CGContextAddLineToPoint(CGContextRef  _Nullable c, CGFloat x, CGFloat y)複製代碼

這樣能夠直接劃線比較簡單,可是隻知足不須要動畫的需求。若是須要進行相似Stroke動畫變須要使用貝塞爾曲線

二、使用貝塞爾曲線與CAShaperLayer結合

初始化一個UIBezierPath

- (UIBezierPath *)bezierPath {
    if (!_bezierPath) {
        _bezierPath = [UIBezierPath bezierPath];
    }
    return _bezierPath;
}複製代碼

經過這個bezierPath進行畫路徑

[_bezierPath moveToPoint:firstPoint];
[_bezierPath addLineToPoint:point];複製代碼

將貝塞爾曲線路徑賦值給CAShapeLayer的路徑

self.shapeLayer.path = self.bezierPath.CGPath;複製代碼

此時已經劃出須要的圖案,接着是執行動畫

- (void)addStrokeEndAnimationToLayer:(CAShapeLayer *)layer {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @0;
    animation.toValue = @1;
    animation.duration = self.animationDuration;
    [layer addAnimation:animation forKey:@"stokeEndAnimation"];
}
//調用動畫
[self addStrokeEndAnimationToLayer:self.shapeLayer];複製代碼

3、展現效果

接下來是展現動畫效果:

animation.gif

相關代碼我都放在 個人Github-AWPolygonView上,後續會有優化更新,有什麼問題歡迎你們提出想法,互相學習進步。
相關文章
相關標籤/搜索