iOS仿支付宝账单饼状图

前言:

  • 这段时间项目做了一个账单查询的页面使用到了饼状图,支付宝账单那个饼状图,就简单的封装了一个给大家看看,使用的基本技术也就是使用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];
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容