實現核心
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開發者們能有一定的幫助,如果有疑問大家可以留言交流。