IOS绘制图形同其它绘制图形的方法相同,首先都需要创建图形上下文,之后push当前要绘制的上下文,设置颜色、阴影等等。。。
代码参考Muh Hon Cheng的PlotCreator的程序。
首先定义类ChartObject用来存储饼图上每个pie的信息
float value;存储当前pie的值
float startAngle;pie的开始的角度
float endAngle;pie的结束角度
NSString *title; 存储当前pie的标题
UIColor *color; 存储当前pie的颜色
ChartObject类具体代码如下:
@interface ChartObject : NSObject
{
float value;
float startAngle;
float endAngle;
NSString *title;
UIColor *color;
}
@property (nonatomic, assign)float value, startAngle, endAngle;
@property (nonatomic, strong)NSString *title;
@property (nonatomic, strong)UIColor *color;
- (id)initWithTitle:(NSString*)_title value:(float)_value;
+ (id)pieComponentWithTitle:(NSString*)_title value:(float)_value;
@end
@implementation ChartObject
@synthesize value,startAngle,endAngle,title,color;
- (id)initWithTitle:(NSString *)_title value:(float)_value
{
self = [super init];
if (self) {
self.title = _title;
self.value = _value;
self.color = PCColorDefault;
}
return self;
}
+ (id)pieComponentWithTitle:(NSString*)_title value:(float)_value
{
return [[super alloc]initWithTitle:_title value:_value];
}
- (void)dealloc
{
[title release];
[color release];
[super dealloc];
}
@end
下面定义用于显示的视图类ChartView
ChartView是具体的绘图类
绘图的例子如:
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(ctx);
CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
CGContextSetShadow(ctx, CGSizeMake(0.0f, 0.0f), TOP_MARGIN);
CGContextFillEllipseInRect(ctx, CGRectMake(x, y, diameter, diameter));
UIGraphicsPopContext();
在ChartView类用变量数组存储饼图的信息,数组中的每一项为ChartObject类
ChartObject类中的title和value可以在初始化时定义,开始的角度和结束的角度在ChartView中赋值。
具体计算方法看代码的注释。
代码如下:
@interface ChartView : UIView //显示信息的页面
#define TOP_MARGIN 15 //阴影的宽度
#define LABEL_TOP_MARGIN 15
{
NSMutableArray *chartObjectsArray;
int diameter; //直径
}
@property (strong, nonatomic)NSMutableArray *chartObjectsArray;
@property (assign, nonatomic)int diameter;
@end
@implementation ChartView
@synthesize chartObjectsArray;
@synthesize diameter;
- (id)init
{
self = [super init];
if (self) {
chartObjectsArray = [[NSMutableArray alloc]initWithCapacity:0];
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
- (void)drawRect:(CGRect)rect //UIView 的 drawRect 方法
{
if (self.diameter == 0) {
diameter = MIN(rect.size.width, rect.size.height) - 2*TOP_MARGIN;
}
NSLog(@"diameter = %d",diameter);
float gap = 1; //边缘线宽度
float x = (rect.size.width - diameter)/2;
float y = (rect.size.height - diameter)/2; //圆所在矩形的起始点
NSLog(@"x = %f,y = %f",x,y);
float inner_radius = diameter/2; //半径
float origin_x = x + diameter/2;
float origin_y = y + diameter/2; //rect的中心点origin_x和origin_y。
NSLog(@"origin_x = %f,origin_y = %f",origin_x,origin_y);
// label stuff
//float left_label_y = LABEL_TOP_MARGIN;
//float right_label_y = LABEL_TOP_MARGIN;//左右标题方块的阴影
if ([chartObjectsArray count]>0)
{
float total = 0;
for (ChartObject *component in chartObjectsArray)
{
total += component.value;
}//total为计算后总的值
/*-----------------------------------画阴影画圆-----------------------------------*/
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(ctx); //获取图像上下文
CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); // white color
CGContextSetShadow(ctx, CGSizeMake(0.0f, 0.0f), TOP_MARGIN);//TOP_MARGIN阴影的宽度
CGContextFillEllipseInRect(ctx, CGRectMake(x, y, diameter, diameter));//画白圆
UIGraphicsPopContext(); //pop图像上下文
/*-----------------------------------画阴影画圆-----------------------------------*/
float nextStartDeg = 0; //当前项目开始的角度
float endDeg = 0; //当前项目结束的角度
for (int i=0; i<[chartObjectsArray count]; i++)
{
/*-----------------------------------画饼图-----------------------------------*/
ChartObject *component = [chartObjectsArray objectAtIndex:i];
float perc = [component value]/total; //当前项目占总项目的百分比
endDeg = nextStartDeg+perc*360; //计算结束的角度值
CGContextSetFillColorWithColor(ctx, [component.color CGColor]);//设置填充的颜色
CGContextMoveToPoint(ctx, origin_x, origin_y); //将上下文移动到起始点
CGContextAddArc(ctx, origin_x, origin_y, inner_radius, (nextStartDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0); //画扇型 1顺时针,0逆时针
CGContextClosePath(ctx); //关闭上下文
CGContextFillPath(ctx); //填充视图
CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1);
[component setStartAngle:nextStartDeg];
[component setEndAngle:endDeg];
/*-----------------------------------画饼图-----------------------------------*/
/*-----------------------------------画边缘线----------------------------------*/
CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1); //设置上下文为黑色
CGContextSetLineWidth(ctx, gap); //设置要画的线的宽度
CGContextMoveToPoint(ctx, origin_x, origin_y); //将环境上下文移动到圆心
CGContextAddArc(ctx, origin_x, origin_y, inner_radius, (nextStartDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0); //沿边缘画线
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
/*-----------------------------------画边缘线----------------------------------*/
/*------------------------------------标签-----------------------------------*/
/*
NSInteger O_x,O_y,E_x,E_y = 0; //原点为origin_x,origin_y;半径长度为inner_radius;
UIFont *font =[UIFont fontWithName:@"GeezaPro" size:10];
if (nextStartDeg >= 180 || (nextStartDeg < 180 && endDeg > 270)) //当扇形为左面时
{
NSString *percentageText = [NSString stringWithFormat:@"%@\n%.1f%%",component.title,component.value/total*100];//当前项目占总项目的百分比
NSLog(@"stratplace = %f,endplace = %f",nextStartDeg,endDeg);
NSLog(@"percent = %@",percentageText);
if (endDeg > 270 && nextStartDeg < 180) //二三四象限
{
double o = 90+endDeg-360;
O_x = origin_x - 2*cos(2*M_PI*o/360)*inner_radius;
O_y = origin_y - sin(2*M_PI*o/360)*inner_radius;
E_x = origin_x - cos(2*M_PI*o/360)*inner_radius;
E_y = origin_y + sin(2*M_PI*o/360)*inner_radius;
}
else //nextStartDeg >=180
{
if (endDeg <= 270) //第三象限
{
double o = 270 - endDeg;
double p = nextStartDeg - 180;
double des = abs((origin_x - cos(2*M_PI*o/360)*inner_radius) - (origin_x - sin(2*M_PI*p/360)*inner_radius));
O_x = origin_x - cos(2*M_PI*o/360)*inner_radius - des - 30; //(30)
O_y = origin_y + sin(2*M_PI*o/360)*inner_radius;
E_x = origin_x - sin(2*M_PI*p/360)*inner_radius;
E_y = origin_y + cos(2*M_PI*p/360)*inner_radius; // (30)
}
else
{
if (nextStartDeg >= 270)//第四象限
{
double o = 360 - endDeg;
double p = nextStartDeg - 270;
double des = abs((origin_x - cos(2*M_PI*p/360)*inner_radius) - (origin_x - sin(2*M_PI*o/360)*inner_radius));
O_x = origin_x - cos(2*M_PI*p/360)*inner_radius - des;
O_y = origin_y - cos(2*M_PI*o/360)*inner_radius - 30;//(30)
E_x = origin_x - sin(2*M_PI*o/360)*inner_radius;
E_y = origin_y - sin(2*M_PI*p/360)*inner_radius - 30;//(30)
}
else //三四象限
{
double o = nextStartDeg - 180;
double p = endDeg - 270;
if (sin(2*M_PI*o/360)*inner_radius == cos(2*M_PI*p/360)*inner_radius)//x相等时
{
O_x = origin_x - sin(2*M_PI*o/360)*inner_radius - 40 - 30; //(30)
E_x = origin_x - sin(2*M_PI*o/360)*inner_radius - 30; //(30)
}
else
{
double des = abs((origin_x - sin(2*M_PI*o/360)*inner_radius) - (origin_x - cos(2*M_PI*p/360)*inner_radius));
NSLog(@"des = %f",des);
O_x = MIN((origin_x - sin(2*M_PI*o/360)*inner_radius),(origin_x - cos(2*M_PI*p/360)*inner_radius)) -des - 30; //(30)
E_x = MAX((origin_x - sin(2*M_PI*o/360)*inner_radius),(origin_x - cos(2*M_PI*p/360)*inner_radius)) - 30; //(30)
}
O_y = origin_y - sin(2*M_PI*p/360)*inner_radius;
E_y = origin_y + cos(2*M_PI*o/360)*inner_radius;
}
}
}
CGContextSetFillColorWithColor(ctx, [component.color CGColor]);
CGContextSetShadow(ctx, CGSizeMake(0.0f, 0.0f), 2);
CGRect percFrame = CGRectMake(O_x,O_y,E_x,E_y);//设置方块
NSLog(@"ox = %f,oy = %f,ex = %f,ey = %f",percFrame.origin.x,percFrame.origin.y,percFrame.size.width,percFrame.size.height);
[percentageText drawInRect:percFrame withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentRight];
}
else //当扇形为右面时
{
NSString *percentageText = [NSString stringWithFormat:@"%.1f%%",component.value/total*100];//当前项目占总项目的百分比
NSLog(@"stratplace = %f,endplace = %f",nextStartDeg,endDeg);
NSLog(@"percent = %@",percentageText);
//( >= 180 || 0~180 )
if ((endDeg - nextStartDeg) >= 180) //角度大于等于180时
{
}
else //角度小于180度
{
}
}
*/
/*------------------------------------标签-----------------------------------*/
nextStartDeg = endDeg;
}
}
customTableView *itemTableView = [[customTableView alloc]initWithFrame:CGRectMake(origin_x +diameter, origin_y-inner_radius, 200, 500) style:UITableViewStylePlain];
float total=0;
for (ChartObject *component in chartObjectsArray)
{
total += component.value;
}//total为计算后总的值
[itemTableView setTableitemsArray:chartObjectsArray];
[itemTableView setTot
[self addSubview:itemTableView];
}
- (void)dealloc
{
[chartObjectsArray removeAllObjects];
[chartObjectsArray release];
[super dealloc];
}
@end
文章中如有错误之处,请大家多多批评。