CoreAnimation实现一个折线表
将折现表封装到一个view里,暴露给使用者的只有一个传入数据的方法。
背景色图层应有渐变色效果,且背景色都在坐标轴所包围的象限内
最后当用户调用setData:方法时,绘制折线图
// // ChartLine.h // BoxingChampion //功能:根据传入的数组,绘制折线图 注意 其frame的宽 不能小于20,高不能小于50 // Created by on 14-12-29. // Copyright (c) 2014年 . All rights reserved. // #import <UIKit/UIKit.h> @interface ChartLine : UIView /* 功能:绘制折线图 参数:折线图的数据,如@[@1,@2] 返回值:无 */ -(void)setData:(NSArray *)array_data; @end
在.m文件中,重写-(id)initWithFrame:(CGRect)frame 方法。
一个折线表,我们可以将它分为三个图层来表示:1、坐标轴图层。2、背景色图层。3、数据折线图层。其中坐标图层应设定贝塞尔曲线,根据路径绘制坐标轴。
// 添加坐标轴曲线路径 UIBezierPath *path_coordinate=[[UIBezierPath alloc] init]; [path_coordinate moveToPoint:CGPointMake(8, 12)]; //带有箭头状的坐标轴 [path_coordinate addLineToPoint:CGPointMake(10, 10)]; [path_coordinate addLineToPoint:CGPointMake(12, 12)]; [path_coordinate addLineToPoint:CGPointMake(10, 10)]; [path_coordinate addLineToPoint:CGPointMake(10, self.frame.size.height-10)]; [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-10, self.frame.size.height-10)]; [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-12, self.frame.size.height-12)]; [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-10, self.frame.size.height-10)]; [path_coordinate addLineToPoint:CGPointMake(self.frame.size.width-12, self.frame.size.height-8)]; //坐标轴路径图层 CAShapeLayer *layer_coordinate=[CAShapeLayer layer]; layer_coordinate.frame= CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height); layer_coordinate.lineCap=kCALineCapButt; layer_coordinate.lineWidth=2; layer_coordinate.fillColor=[[UIColor clearColor] CGColor]; layer_coordinate.strokeColor=[[UIColor orangeColor] CGColor]; layer_coordinate.strokeEnd=1; layer_coordinate.path=[path_coordinate CGPath];
背景色图层应有渐变色效果,且背景色都在坐标轴所包围的象限内
//淡色背景图层 CAGradientLayer *layer_background=[CAGradientLayer layer]; layer_background.frame=CGRectMake(11, 13, self.layer.frame.size.width-22,self.layer.frame.size.height-24);//保证在第一象限 [layer_background setColors:[NSArray arrayWithObjects: (id)[[UIColor whiteColor] CGColor], [[UIColor colorWithRed:1.000 green:0.827 blue:0.000 alpha:1.000] CGColor] ,nil]]; layer_background.locations=@[@0.1];//从0.1处开始渐变 location 坐标是左上角(0,0),在右下角(1,1) 使用时应注意 layer_background.startPoint=CGPointMake(0,0); layer_background.endPoint=CGPointMake(0, 1);将两个图层添加到视图图层上
//添加图层 [self.layer addSublayer:layer_coordinate]; [self.layer addSublayer:layer_background];
最后当用户调用setData:方法时,绘制折线图
-(void)setData:(NSArray *)array_data { //获取输入元素的个数 NSInteger i_dataCount=[array_data count]; //取出元素中得最大值和最小值 CGFloat f_maxData=[[array_data objectAtIndex:0] floatValue]; CGFloat f_minData=[[array_data objectAtIndex:0]floatValue]; for (NSInteger i=0;i<i_dataCount; i++) { if (f_maxData<[[array_data objectAtIndex:i] floatValue]) { f_maxData=[[array_data objectAtIndex:i] floatValue]; } if (f_minData>[[array_data objectAtIndex:i] floatValue]) { f_minData=[[array_data objectAtIndex:i] floatValue]; } } //计算每个数据之间横坐标的间隔 CGFloat x_perDataPointInterval=(self.layer.frame.size.width-20)/(i_dataCount+1); if (0==(f_maxData-f_minData))//防止分母为零 { NSLog(@"Y轴逻辑最大值和逻辑最小值相同"); return; } //计算每个数据1 占据几个像素点 CGFloat y_perPointInterval=(self.layer.frame.size.height-50)/(f_maxData-f_minData); //折线路径 UIBezierPath *path_data=[[UIBezierPath alloc] init]; //第一个元素起始点的坐标 [path_data moveToPoint:CGPointMake(10+x_perDataPointInterval, self.layer.frame.size.height-(20+([[array_data objectAtIndex:0] floatValue]-f_minData)*y_perPointInterval))]; for (NSInteger i=0; i<i_dataCount-1; i++) { //每个元素在视图中的坐标 [path_data addLineToPoint:CGPointMake(10+x_perDataPointInterval*(i+2), self.layer.frame.size.height-(20+([[array_data objectAtIndex:(i+1)] floatValue]-f_minData)*y_perPointInterval))]; } //折线图层 CAShapeLayer *layer_data=[CAShapeLayer layer]; layer_data.frame=CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height); layer_data.lineCap=kCALineCapRound; layer_data.lineWidth=1; layer_data.fillColor=[[UIColor clearColor] CGColor]; layer_data.strokeColor=[[UIColor redColor] CGColor]; layer_data.strokeEnd=1; layer_data.path=[path_data CGPath]; [self.layer addSublayer:layer_data]; }