前言:
- 這段時間項目做了一個賬單查詢的頁面使用到了餅狀圖,支付寶賬單那個餅狀圖,就簡單的封裝了一個給大家看看,使用的基本技術也就是使用UIBezierPath繪制柱狀圖路徑,再把CAShapeLayer和UIBezierPath建立關系,最后使用CABasicAnimation實現簡單的動畫效果。
先看下效果圖:動畫太快了注意看吧
Untitled.gif
1.繪制餅狀圖
繪制餅狀圖計算每個扇形弧度中心點坐標記錄成員變量給指示線起點&指示線起點圓點使用
#pragma mark ------ 繪制餅狀圖 ------- - (void)addPieChart:(CAShapeLayer *)layer andArcCenter:(CGPoint)ArcCenter andStart_Angle:(CGFloat)start_Angle andend_Angle:(CGFloat)end_Angle andPieChartWidht:(CGFloat)PieChartWidht andandPieChartColor:(UIColor *)andPieChartColor{
UIBezierPath * progressPath = [UIBezierPath bezierPathWithArcCenter:ArcCenter radius:PieChartRadius startAngle:DEGREES_TO_VALUE(start_Angle) endAngle:DEGREES_TO_VALUE(end_Angle) clockwise:YES]; layer.path = progressPath.CGPath; layer.lineWidth = PieChartWidht; layer.strokeColor = andPieChartColor.CGColor;
// 計算存儲圓弧中心點到數組 // 弧度的中心角度 CGFloat RadianCentreCoordinate = (DEGREES_TO_VALUE(start_Angle) + DEGREES_TO_VALUE(end_Angle)) / 2.0;
// 記錄小圓的中心點(折現起始點) ArcCentreCoordinate.x = ArcCenter.x+(PieChartRadius+40) * cos(RadianCentreCoordinate); ArcCentreCoordinate.y = ArcCenter.y+(PieChartRadius+40) * sin(RadianCentreCoordinate); }
2.餅狀圖動畫添加
餅狀圖繪制是基于UIBezierPath所有添加動畫使用CABasicAnimation
#pragma mark ------ 餅狀圖動畫添加 ------- - (void)addPieChart:(CAShapeLayer *)layer andArcCenter:(CGPoint)ArcCenter andStart_Angle:(CGFloat)start_Angle andend_Angle:(CGFloat)end_Angle andPieChartWidht:(CGFloat)PieChartWidht andPieChartColor:(UIColor *)PieChartColor animated:(BOOL)animated{
[self addPieChart:layer andArcCenter:ArcCenter andStart_Angle:start_Angle andend_Angle:end_Angle andPieChartWidht:PieChartWidht andandPieChartColor:PieChartColor];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = end_Angle*0.01;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[layer addAnimation:pathAnimation forKey:nil]; }
3.繪制指示線
這個指示線挺煩,坐標系原理你們自己看看吧。
#pragma mark ------ 繪制指示線 ------- - (CGPoint)addIndicatrixLine:(CAShapeLayer *)layer andOriginCoordinate:(CGPoint)OriginCoordinate andIndicatrixLineLength:(CGFloat)IndicatrixLineLength andIndicatrixLineWidth:(CGFloat)IndicatrixLineWidth andIndicatrixLineColor:(UIColor *)IndicatrixLineColor{ //起點坐標 CGFloat IndicatrixLine_Origin_CoordInateX = OriginCoordinate.x; CGFloat IndicatrixLine_Origin_CoordInateY = OriginCoordinate.y;
//圓點坐標 [self addIndicatrixLine_Origin_Style:CGPointMake(IndicatrixLine_Origin_CoordInateX, IndicatrixLine_Origin_CoordInateY) andColor:IndicatrixLineColor];
//終點坐標 CGFloat IndicatrixLine_End_CoordInateX; CGFloat IndicatrixLine_End_CoordInateY;
UIBezierPath * IndicatrixLine = [UIBezierPath bezierPath];
//指示線第一段(小段) if (IndicatrixLine_Origin_CoordInateX < ARCCENTER.x) {
if (IndicatrixLine_Origin_CoordInateY < ARCCENTER.y) {
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x-10; IndicatrixLine_End_CoordInateY = OriginCoordinate.y-10; }else{
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x-10; IndicatrixLine_End_CoordInateY = OriginCoordinate.y+10; } }else{
if (IndicatrixLine_Origin_CoordInateY < ARCCENTER.y) {
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x+10; IndicatrixLine_End_CoordInateY = OriginCoordinate.y-10; }else{
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x+10; IndicatrixLine_End_CoordInateY = OriginCoordinate.y+10; } }
[IndicatrixLine moveToPoint:CGPointMake(IndicatrixLine_Origin_CoordInateX, IndicatrixLine_Origin_CoordInateY)]; [IndicatrixLine addLineToPoint:CGPointMake(IndicatrixLine_End_CoordInateX, IndicatrixLine_End_CoordInateY)];
//畫完第一段(小段)把小段的終點賦值給第二段(大段)當起點 IndicatrixLine_Origin_CoordInateX = IndicatrixLine_End_CoordInateX; IndicatrixLine_Origin_CoordInateY = IndicatrixLine_End_CoordInateY;
//指示線第二段(大段) if (IndicatrixLine_Origin_CoordInateX < ARCCENTER.x) {
if (IndicatrixLine_Origin_CoordInateY < ARCCENTER.y) {
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x-IndicatrixLineLength; IndicatrixLine_End_CoordInateY = OriginCoordinate.y-10; }else{
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x-IndicatrixLineLength; IndicatrixLine_End_CoordInateY = OriginCoordinate.y+10; }
}else{
if (IndicatrixLine_Origin_CoordInateY < ARCCENTER.y) {
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x+IndicatrixLineLength; IndicatrixLine_End_CoordInateY = OriginCoordinate.y-10; }else{
//終點坐標 IndicatrixLine_End_CoordInateX = OriginCoordinate.x+IndicatrixLineLength; IndicatrixLine_End_CoordInateY = OriginCoordinate.y+10; } }
[IndicatrixLine moveToPoint:CGPointMake(IndicatrixLine_Origin_CoordInateX, IndicatrixLine_Origin_CoordInateY)]; [IndicatrixLine addLineToPoint:CGPointMake(IndicatrixLine_End_CoordInateX, IndicatrixLine_End_CoordInateY)];
layer.path = IndicatrixLine.CGPath; layer.lineWidth = IndicatrixLineWidth; layer.strokeColor = IndicatrixLineColor.CGColor;
return CGPointMake(IndicatrixLine_End_CoordInateX, IndicatrixLine_End_CoordInateY); }
4.指示線添加動畫
和餅狀圖動畫添加是一樣的
#pragma mark ------ 指示線動畫添加 ------- - (CGPoint)addIndicatrixLine:(CAShapeLayer *)layer andOriginCoordinate:(CGPoint)OriginCoordinate andIndicatrixLineLength:(CGFloat)IndicatrixLineLength andIndicatrixLineWidth:(CGFloat)IndicatrixLineWidth andIndicatrixLineColor:(UIColor *)IndicatrixLineColor animated:(BOOL)animated{
CGPoint TextCoordinate = [self addIndicatrixLine:layer andOriginCoordinate:OriginCoordinate andIndicatrixLineLength:IndicatrixLineLength andIndicatrixLineWidth:IndicatrixLineWidth andIndicatrixLineColor:IndicatrixLineColor];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = IndicatrixLineLength*0.01;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[layer addAnimation:pathAnimation forKey:nil];
return TextCoordinate; }
5.指示線起點樣式
這個是繪制了一個小圓點作為指示線起點
#pragma mark ------ 繪制指示線起點樣式 ------- - (void)addIndicatrixLine_Origin_Style:(CGPoint)coordinate
andColor:(UIColor *)indicatrixLineColor{
CAShapeLayer *circleLayer = [CAShapeLayer layer]; // 指定frame,只是為了設置寬度和高度 circleLayer.frame = CGRectMake(0, 0, 2, 2); // 設置居中顯示 circleLayer.position = CGPointMake(coordinate.x, coordinate.y); // 設置填充顏色 circleLayer.fillColor = [UIColor clearColor].CGColor; // 設置線寬 circleLayer.lineWidth = 2.0; // 設置線的顏色 circleLayer.strokeColor = indicatrixLineColor.CGColor;
// 使用UIBezierPath創建路徑 CGRect frame = CGRectMake(0, 0, 2, 2); UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
// 設置CAShapeLayer與UIBezierPath關聯 circleLayer.path = circlePath.CGPath;
// 將CAShaperLayer放到某個層上顯示 [self.layer addSublayer:circleLayer]; }
5.指示線上下文字繪制
指示線上下文字繪制這個么什么好說的
#pragma mark ------ 繪制指示文字 ------- - (void)addHintText:(CGPoint)TextCoordinate andabovetext:(NSString *)abovetext andDowntext:(NSString *)Downtext andTextFont:(CGFloat)font andTextColor:(UIColor *)color{
// 上面Size CGSize abovetextSize = [abovetext sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:font]}]; // 下面Size CGSize DowntextSize = [Downtext sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:font]}];
//上面文字坐標 CGFloat abovetextCoordinateX; CGFloat abovetextCoordinateY; //下面文字坐標 CGFloat DowntextCoordinateX; CGFloat DowntextCoordinateY;
if (ARCCENTER.x < TextCoordinate.x) {
abovetextCoordinateX = TextCoordinate.x-abovetextSize.width; abovetextCoordinateY = TextCoordinate.y-abovetextSize.height;
DowntextCoordinateX = TextCoordinate.x-DowntextSize.width; DowntextCoordinateY = TextCoordinate.y; }else{
abovetextCoordinateX = TextCoordinate.x; abovetextCoordinateY = TextCoordinate.y-abovetextSize.height;
DowntextCoordinateX = TextCoordinate.x; DowntextCoordinateY = TextCoordinate.y; }
NSMutableParagraphStyle * paragraph = [[NSMutableParagraphStyle alloc]init]; paragraph.alignment = NSTextAlignmentLeft;
//指引線上面的數字 [abovetext drawAtPoint:CGPointMake(abovetextCoordinateX, abovetextCoordinateY) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:font],NSForegroundColorAttributeName:color,NSParagraphStyleAttributeName:paragraph}]; //指示線下面的文字 [Downtext drawAtPoint:CGPointMake(DowntextCoordinateX, DowntextCoordinateY)
withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:font],
NSForegroundColorAttributeName:color,
NSParagraphStyleAttributeName:paragraph}];
}
6. drawRect繪制調用
- (void)drawRect:(CGRect)rect { // Drawing code
NSArray * RedAarray = @[@"46",@"255",@"62",@"254",@"253",@"153",@"110"]; NSArray * greenArray = @[@"191",@"48",@"209",@"199",@"109",@"208",@"123"]; NSArray * blueArray = @[@"238",@"145",@"185",@"17",@"31",@"60",@"254"];
for (int i = 0; i < _ArcCentreCoordinateAll.count; i++) {
CAShapeLayer * progressLayer = [CAShapeLayer new]; [self.layer addSublayer:progressLayer]; progressLayer.fillColor = nil; progressLayer.frame = self.bounds;
end = start+[[_ArcCentreCoordinateAll objectAtIndex:i] floatValue];
NSMutableArray * startORendArray = [[NSMutableArray alloc]init]; [startORendArray addObject:[NSString stringWithFormat:@"%f",start]]; [startORendArray addObject:[NSString stringWithFormat:@"%f",end]];
start = end;
/* @1.addPieChart:CAShapeLayer對象 @2.andArcCenter:餅狀圖中心坐標 @3.andStart_Angle:餅狀圖起點位置 @4.andend_Angle:餅狀圖結束點位置 @5.andPieChartColor:餅狀圖顏色 @6.animated:是否添加動畫 */
[self addPieChart:progressLayer andArcCenter:ARCCENTER andStart_Angle:[startORendArray[0] floatValue] andend_Angle:[startORendArray[1] floatValue] andPieChartWidht:_PieChartWidth andPieChartColor:[UIColor colorWithRed:[[RedAarray objectAtIndex:i] intValue]/255.0 green:[[greenArray objectAtIndex:i] intValue]/255.0 blue:[[blueArray objectAtIndex:i] intValue]/255.0 alpha:1]
animated:YES];
CAShapeLayer * IndicatrixLayer = [CAShapeLayer new]; [self.layer addSublayer:IndicatrixLayer]; IndicatrixLayer.fillColor = nil; IndicatrixLayer.frame = self.bounds;
/* @1.addIndicatrixLine:CAShapeLayer對象 @2.andOriginCoordinate:指示線&線帽起點坐標 @3.andIndicatrixLineLength:指示線長度 @4.andIndicatrixLineLength:指示線寬度 @5.andIndicatrixLineColor:指示線顏色 @6.animated:是否添加動畫 */
CGPoint TextCoordinate = [self addIndicatrixLine:IndicatrixLayer
andOriginCoordinate:ArcCentreCoordinate
andIndicatrixLineLength:_IndicatrixLineLength
andIndicatrixLineWidth:_IndicatrixLineWidth
andIndicatrixLineColor:[UIColor colorWithRed:[[RedAarray objectAtIndex:i] intValue]/255.0 green:[[greenArray objectAtIndex:i] intValue]/255.0 blue:[[blueArray objectAtIndex:i] intValue]/255.0 alpha:1]
animated:YES];
/* @1.addHintText:文字坐標 @2.andabovetext:上面文字 @3.andDowntext:下面文字 @4.andTextFont:文字大小 @5.andTextColor:文字顏色 */
[self addHintText:TextCoordinate
andabovetext:_aboveHintTextAttayAll[i]
andDowntext:_belowHintTextAttayAll[i]
andTextFont:_HintTextFont
andTextColor:_HintTextColor];
} }