iOS绘制3D饼图的实现方法

实现核心

1.压缩饼图,使饼图有3D的效果,并不是真正的画了个3D圆柱

2.绘制厚度,带阴影效果,让看上去像是圆柱的高

3.路径添加好了,用颜色填充后绘制一下,添加阴影后还需绘制一遍

饼图添加阴影的思考

之前这加阴影的一段不是很明白,为啥设颜色和阴影都要draw一次

进过反复的测试,我自己分析了一下,每次draw一下想当于,把当前的设置画出来,再次draw就在这基础上,再画最近的设置,这里加颜色和阴影就像是一层一层的画上去。要是不draw的话,再设置颜色相当于重新设置了颜色,之前设置的颜色就无效了。同时要结合path使用,如果设置一场颜色draw一次,再设置颜色draw一次,后面设置的颜色是无用的。需要添加阴影的部分,需要用path路径绘制。

效果图

3D饼图的核心代码如下:

#import "SSSolidCakeView.h"

@implementation SSSolidCakeView
#pragma mark 重写绘制方法
- (void)drawRect:(CGRect)rect
{
  //第一步获得上下文
  CGContextRef cakeContextRef = UIGraphicsGetCurrentContext();
  //反锯齿,让图形边缘更加柔和(Sets whether or not to allow anti-aliasing for a graphics context.)
  CGContextSetAllowsAntialiasing(cakeContextRef, TRUE);
  //缩放坐标系的比例,通过设置y轴压缩,然后画代阴影的厚度,就画出了像是3D饼图的效果
  CGContextScaleCTM(cakeContextRef, _xScale, _yScale);
  //饼图最先的起始角度
  CGFloat startAngle =0;

  for (int i = 0; i<_dataArray.count; i++) {
    //画饼的横截面,上一部分完整的圆
    //cake当前的角度
    CGFloat currentAngle = [_dataArray[i] floatValue];
    //结束的角度
    CGFloat endAngle = startAngle + currentAngle;
    //每一块cake的起点,也就是圆心
    CGContextMoveToPoint(cakeContextRef, _cakeCenter.x, _cakeCenter.y);

    //添加对应角度扇形
    CGContextAddArc(cakeContextRef, _cakeCenter.x, _cakeCenter.y, _cakeRadius, startAngle*M_PI*2, endAngle*M_PI*2, 0);

    //得到对应的颜色
    UIColor *currentColor = _colorArray[i];
    //设置边界颜色
    CGContextSetStrokeColorWithColor(cakeContextRef, currentColor.CGColor);
    //设置填充颜色
    CGContextSetFillColorWithColor(cakeContextRef, currentColor.CGColor);
    //画子路径,这里就绘制还不是在画完厚度再绘制,是因为并不需要绘制所有cake的厚度,但是上一部分的圆是都要绘制的
    CGContextDrawPath(cakeContextRef, kCGPathFill);
    //饼图上一部分圆,startAngle处的起点坐标
    CGFloat upStartX = _cakeCenter.x+_cakeRadius*cos(startAngle*2*M_PI);
    CGFloat upStartY = _cakeCenter.y+_cakeRadius*sin(startAngle*2*M_PI);
    //饼图上一部分圆,endAngle处的终点坐标
    CGFloat upEndX = _cakeCenter.x+_cakeRadius*cos(endAngle*2*M_PI);
    CGFloat upEndY = _cakeCenter.y+_cakeRadius*sin(endAngle*2*M_PI);

    //饼图厚度在角度结束处y坐标
    CGFloat downEndY = upEndY + _cakeHeight;
    //画圆柱的侧面,饼图的厚度,圆柱的前半部分能看到,后半部分是看不到
    //开始的角度如果>=M_PI,就会在圆柱的后面,侧面厚度就没必要画了
    if (startAngle<0.5) {
      //绘制厚度
      CGMutablePathRef path = CGPathCreateMutable();
      CGPathMoveToPoint(path, nil, upStartX, upStartY);
      //当结束的角度>0.5*2*M_PI时,结束的角度该是M_PI的地方(视觉原因)
      if (endAngle>0.5) {
        //上部分的弧
        CGPathAddArc(path, nil, _cakeCenter.x, _cakeCenter.y, _cakeRadius, startAngle*2*M_PI, M_PI, 0);
        //在角度结束的地方,上部分到下部分的直线
        CGPathAddLineToPoint(path, nil, _cakeCenter.x-_cakeRadius, _cakeCenter.y+_cakeHeight);
        //下部分的弧
        CGPathAddArc(path, nil, _cakeCenter.x, _cakeCenter.y + _cakeHeight, _cakeRadius, M_PI, startAngle*2*M_PI, 1);
        //在角度开始的地方,从下部分到上部分的直线
        CGPathAddLineToPoint(path, nil, upStartX, upStartY);

      }
      else{
        //上部分的弧
        CGPathAddArc(path, nil, _cakeCenter.x, _cakeCenter.y, _cakeRadius, startAngle*2*M_PI, endAngle*2*M_PI, 0);
        //在角度结束的地方,上部分到下部分的直线
        CGPathAddLineToPoint(path, nil, upEndX, downEndY);
        //下部分的弧
        CGPathAddArc(path, nil, _cakeCenter.x, _cakeCenter.y + _cakeHeight, _cakeRadius, endAngle*2*M_PI, startAngle*2*M_PI, 1);
        //在角度开始的地方,从下部分到上部分的直线
        CGPathAddLineToPoint(path, nil, upStartX, upStartY);

      }
      //之前这一段不是很明白,为啥设颜色和阴影都要draw一次
      //我自己尝试并理解分析了一下,每次draw一下想当于,把当前的设置画出来,再次draw就在这基础上,再画当前的设置,这里加颜色和阴影就是一层一层的画上去。要是不draw的话,再设置颜色相当于重新设置了颜色,之前设置的颜色就无效了。
      CGContextAddPath(cakeContextRef, path);
      CGContextDrawPath(cakeContextRef, kCGPathFill);
      //加阴影
      [[UIColor colorWithWhite:0.2 alpha:0.4] setFill];
      CGContextAddPath(cakeContextRef, path);
      CGContextDrawPath(cakeContextRef, kCGPathFill);

    }

    //最后一句,上一块的结束角度是下一块的开始角度
    startAngle = endAngle;

  }
  //此时不能用以下的方法填充,会导致饼图就一种颜色
  //CGContextFillPath(contextRef);
}
-(void)setDataArray:(NSArray *)dataArray
{
  _dataArray = dataArray;
  //重新绘制
  [self setNeedsDisplay];
}

这里要说明一下,我的数组是百分比数组,由数值转化为百分比的过程我没有在这里处理。

如何使用view:

  self.solidCakeView = [[SSSolidCakeView alloc]init];
  self.solidCakeView.dataArray = _dataArray;
  self.solidCakeView.colorArray = _colorArray;
  self.solidCakeView.nameArray = _nameArray;
  self.solidCakeView.cakeCenter = CGPointMake(200, 200);
  self.solidCakeView.cakeRadius = 100;
  self.solidCakeView.cakeHeight = 30;
  self.solidCakeView.xScale = 1;
  self.solidCakeView.yScale = 0.8;
  self.solidCakeView.backgroundColor = [UIColor whiteColor];
  self.solidCakeView.frame = CGRectMake(0, 0, PhoneScreen_WIDTH-100, PhoneScreen_HEIGHT-20);
  [self.view addSubview:self.solidCakeView];

3D饼图如何绘制及使用已经用代码介绍完了,相信看到这大家应该也能实现3D饼图了。

本文参考了:http://blog.csdn.net/donny_zhang/article/details/9145379  感谢博主!

总结

以上就是这篇文章的全部内容了,希望本文的内容对各位iOS开发者们能有一定的帮助,如果有疑问大家可以留言交流。

时间: 2017-01-04

iOS使用Charts框架绘制折线图

首先先看一下效果: 折线图 一. 初始化折线图对象 创建一个折线图的用到的类是LineChartView.h, 代码如下: self.LineChartView = [[LineChartView alloc] init]; self.LineChartView.delegate = self;//设置代理 [self.view addSubview:self.LineChartView]; [self.LineChartView mas_makeConstraints:^(MASConstra

iOS 生成图片验证码绘制实例代码

登录注册时用的验证码效果图 ViewDidload调用即可 _pooCodeView = [[PooCodeView alloc] initWithFrame:CGRectMake(50, 100, 82, 32)]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)]; [_pooCodeView addGestureReco

IOS 绘制三角形的实例详解

IOS 绘制三角形的实例详解 先上效果图 上面三角形的代码 - (void)ljTestView { CGPoint piont1; piont1.x = 170; piont1.y = 100; CGPoint piont2; piont2.x = 50; piont2.y = 200; CGPoint piont3; piont3.x = 220; piont3.y = 200; ljDrawRect *_ljView = [[ljDrawRect alloc]initStartPoint:

iOS App开发中用CGContextRef绘制基本图形的基本示例

Graphics Context是图形上下文,也可以理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框. CGContextRef功能强大,我们借助它可以画各种图形.开发过程中灵活运用这些技巧,可以帮助我们提供代码水平. 首先创建一个集成自UIView的,自定义CustomView类. 在CustomView.m中实现代码. 复制代码 代码如下: #import <QuartzCore/QuartzCore.h> 覆盖DranRe

iOS使用Charts框架绘制饼状图

首先先看一下效果: 饼状图 一.创建饼状图对象 创建饼状图对象用到类是PieChartView.h, 代码如下: self.pieChartView = [[PieChartView alloc] init]; self.pieChartView.backgroundColor = BgColor; [self.view addSubview:self.pieChartView]; [self.pieChartView mas_makeConstraints:^(MASConstraintMak

IOS绘制动画颜色渐变折线条

先给大家展示下效果图: 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有的也使用了动画,但是线条颜色渐变的折线图的demo少之又少,甚至可以说没有.该Blog阐述了动画绘制线条颜色渐变的折线图的实现方案,以及折线图线条颜色渐变的实现原理,并附以完整的示例. 成果 本人已将折线图封装到了一个UIView子类中,并提供了相应的接口.该自定义折线图视图,基本上可以适用于大部分需要集成折线图的项目.若你

IOS绘制虚线的方法总结

一.重写drawRect方法. - (void)drawRect:(CGRect)rect { [super drawRect:rect]; CGContextRef currentContext = UIGraphicsGetCurrentContext(); //设置虚线颜色 CGContextSetStrokeColorWithColor(currentContext, [UIColor BlackColor].CGColor); //设置虚线宽度 CGContextSetLineWidt

Android自定义View实现绘制虚线的方法详解

前言 说实话当第一次看到这个需求的时候,第一反应就是Canvas只有drawLine方法,并没有drawDashLine方法啊!这咋整啊,难道要我自己做个遍历不断的drawLine?不到1秒,我就放弃这个想法了,因为太恶心了.方法肯定是有的,只不过我不知道而已. 绘制方法 最简单的方法是利用ShapeDrawable,比如说你想用虚线要隔开两个控件,就可以在这两个控件中加个View,然后给它个虚线背景. 嗯,理论上就是这样子的,实现上也很简单. <!-- drawable 文件 --> <

利用iOS绘制图片生成随机验证码示例代码

先来看看效果图 实现方法 .h文件 @property (nonatomic, retain) NSArray *changeArray; @property (nonatomic, retain) NSMutableString *changeString; @property (nonatomic, retain) UILabel *codeLabel; -(void)changeCode; @end .m文件 @synthesize changeArray = _changeArray;

iOS常用的公共方法详解

1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat size = 0.0; NSError *error; NSDictionary *dic = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error]; if (error) { #ifdef DEBUG NSLog(@"error: %

ichart.js绘制虚线、平均分虚线效果的实现代码

ichart.js绘制虚线.平均分虚线效果的实现代码 var Data=new Array(); Data[0] = { labels : ["第一单元","第二单元","第三单元","第四单元","第五单元"], datasets : [ { name : '优秀率', color:'#1dbcfe', line_width:4, value : [80,75,92,62,0] } ] } Data[1]

C#绘制曲线图的方法

本文实例讲述了C#绘制曲线图的方法.分享给大家供大家参考.具体如下: 1. 曲线图效果: 2. C#代码: /// <summary> /// 自动根据参数调整图像大小 /// </summary> public void Fit() { //计算字体距离 intFontSpace = FontSize + 5; //计算图像边距 float fltSpace = Math.Min(Width / 6, Height / 6); XSpace = fltSpace; YSpace

python利用matplotlib库绘制饼图的方法示例

介绍 matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图.而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中. 它的文档相当完备,并且 Gallery页面 中有上百幅缩略图,打开之后都有源程序.因此如果你需要绘制某种类型的图,只需要在这个页面中浏览/复制/粘贴一下,基本上都能搞定. matplotlib的安装方法可以点击这里 这篇文章给大家主要介绍了python用matplotlib绘制饼图的方法,话不多说,下面来看代码

iOS UIView常见属性方法小结

下面通过实例代码给大家详细介绍了iOS UIView常见属性方法,具体代码如下所示: UIView : UIResponder /** 通过一个frame来初始化一个UI控件 */ - (id)initWithFrame:(CGRect)frame; // YES:能够跟用户进行交互 @property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is YES // 控件的一