本文首發於:個人簡書javascript
#前言java
能力分佈圖是一個統計類常常須要的一個需求,須要必定的幾何計算,實現難度適中,在平時也很適合拿來用做iOS繪圖練手。
這裏寫了一個具備必定可複用行比較高的多邊形能力分佈圖,有須要的同窗能夠拿去用,也能夠當作本身的練手Demo。相關代碼我都放在個人Github-AWPolygonView上,後續會有優化更新,有什麼問題歡迎你們提出想法,互相學習進步。git
畫圖一個核心步驟是計算須要的點的座標。須要的點的類型爲:中心點、邊上的角、能力值的各個點。接下來開始計算各個點的座標。github
x座標就是View的寬度的一半
y座標就是View的高度的一半ide
_centerX = self.bounds.size.width/2;
_centerY = self.bounds.size.height/2;複製代碼
根據須要是幾邊形,經過在一個以View的中心點爲圓心,view的寬度爲直徑的圓上取點。
而後經過角度和半徑 進行計算得到各個點的座標cos
和sin
方法參數須要爲弧度,將其轉換成傳入參數爲角度的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]];
}
}複製代碼
各個點的座標肯定好了,接下來就是連線了,能夠採用CoreGraphics中的context繪製直線方法:code
CGContextMoveToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y)
CGContextAddLineToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y)複製代碼
這樣能夠直接劃線比較簡單,可是隻知足不須要動畫的需求。若是須要進行相似Stroke
動畫變須要使用貝塞爾曲線
初始化一個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];複製代碼
接下來是展現動畫效果: