iOS绘制3D饼图的实现方法
程序员文章站
2024-02-18 20:26:28
实现核心
1.压缩饼图,使饼图有3d的效果,并不是真正的画了个3d圆柱
&nb...
实现核心
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开发者们能有一定的帮助,如果有疑问大家可以留言交流。