前言:
- 这段时间项目做了一个账单查询的页面使用到了饼状图,支付宝账单那个饼状图,就简单的封装了一个给大家看看,使用的基本技术也就是使用UIBezierPath绘制柱状图路径,再把CAShapeLayer和UIBezierPath建立关系,最后使用CABasicAnimation实现简单的动画效果。
看下效果图:

前言:
- 这段时间项目做了一个账单查询的页面使用到了饼状图,支付宝账单那个饼状图,就简单的封装了一个给大家看看,使用的基本技术也就是使用UIBezierPath绘制柱状图路径,再把CAShapeLayer和UIBezierPath建立关系,最后使用CABasicAnimation实现简单的动画效果。
看下效果图:
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];
}
}