swift版:https://www.jianshu.com/p/f581194cb02c
预览
变量初始化
//内边距
static CGFloat borderX = 40;
static CGFloat borderY = 20;
//x和y的个数
//x = 4: 2014,2015,2016,2017
//y = 6: 0,500,100,1500,2000,2500
static CGFloat x = 4;
static CGFloat y = 6;
//x和y每个单位代表的值
static CGFloat yValue = 500;
static CGFloat xValue = 1;
//x和y的起始值
static CGFloat yStart = 0;
static CGFloat xStart = 2014;
//x和y的单位长度
CGFloat widthX;
CGFloat heightY;
构造函数
-(instancetype)initWithArrayAndFrame:(NSArray *)array andFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor whiteColor];
self.array = array;
//计算单位长度
widthX = (self.frame.size.width-borderX*2)/x;
heightY = (self.frame.size.height-borderY*2)/y;
//画x轴的label:2014,2015...
[self drawX];
//画y轴的label:0,500,1000...
[self drawY];
//画折线
[self drawLine];
}
return self;
}
画坐标轴,虚线,和数据点
-(void)drawRect:(CGRect)rect{
//画坐标轴
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetLineWidth(context, 1);
CGContextMoveToPoint(context, borderX, borderY);
CGContextAddLineToPoint(context, borderX, rect.size.height-borderY);
CGContextAddLineToPoint(context, rect.size.width-borderX, rect.size.height-borderY);
CGContextStrokePath(context);
//画y轴的分割虚线
CGContextRef context2 = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextSetLineWidth(context2, 1);
for (int i=1; i<y; i++) {
UILabel *yLabel = (UILabel*)[self viewWithTag:2000 + i];
CGContextMoveToPoint(context2, borderX-3, yLabel.frame.origin.y+heightY/2);
CGContextAddLineToPoint(context2, rect.size.width-borderX, yLabel.frame.origin.y+heightY/2);
}
CGContextStrokePath(context2);
//画x轴的分割点
CGContextRef context3 = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context3, [UIColor lightGrayColor].CGColor);
CGContextSetLineWidth(context3, 1);
for (int i=0; i<x; i++) {
//通过tag获取x轴对应label
UILabel *xLabel = (UILabel*)[self viewWithTag:1000 + i];
CGContextMoveToPoint(context3, xLabel.frame.origin.x+widthX, rect.size.height-borderY);
CGContextAddLineToPoint(context3, xLabel.frame.origin.x+widthX, rect.size.height-borderY+5);
}
CGContextStrokePath(context3);
//画传入数组值对应的点
CGContextRef context4 = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetLineWidth(context, 2.0);
//y轴的总值
float yTotalValue = yStart + yValue*y;
//y轴的长度
float height = self.frame.size.height - borderY*2;
for (int i=0; i<x; i++) {
//计算点的纵坐标
float pointy = self.frame.size.height - [self.array[i] floatValue]/yTotalValue*height - borderY;
CGContextMoveToPoint(context4, widthX/2+widthX*i+borderX, pointy);
// x,y为圆点坐标,radius半径,startAngle为开始的弧度,endAngle为 结束的弧度,clockwise 0为顺时针,1为逆时针。
CGContextAddArc(context4, widthX/2+widthX*i+borderX, pointy, 5, 0, 2*M_PI, 0);
}
CGContextDrawPath(context4, kCGPathFill);
}
写X轴Y轴的数字
-(void)drawX{
for (int i=0; i<x; i++) {
UILabel *xLabel = [[UILabel alloc]initWithFrame:CGRectMake(borderX+widthX*i, self.frame.size.height-borderY+5, widthX, 10)];
NSInteger x = xStart+xValue*i;
xLabel.text = [NSString stringWithFormat:@"%ld",x];
xLabel.font = [UIFont systemFontOfSize:10];
[xLabel setTextAlignment:NSTextAlignmentCenter];
//设置tag,画分割线的时候用
xLabel.tag = 1000+i;
[self addSubview:xLabel];
}
}
-(void)drawY{
for (int i=0; i<y; i++) {
UILabel *yLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, self.frame.size.height-borderY-heightY/2-heightY*i, 35, heightY)];
NSInteger y = yStart+yValue*i;
yLabel.text = [NSString stringWithFormat:@"%ld",y];
yLabel.font = [UIFont systemFontOfSize:10];
[yLabel setTextAlignment:NSTextAlignmentRight];
yLabel.tag = 2000+i;
[self addSubview:yLabel];
}
}
画折线
-(void)drawLine{
float yTotalValue = yStart + yValue*y;
float height = self.frame.size.height - borderY*2;
float pointy = self.frame.size.height - [self.array[0] floatValue]/yTotalValue*height - borderY;
//在第一个点下方写数值
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(widthX/2+borderX, pointy, 50, 20)];
label.text = [NSString stringWithFormat:@"%ld",[self.array[0] integerValue]];
label.font = [UIFont systemFontOfSize:10];
[self addSubview:label];
//贝塞尔曲线设置起始点
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:CGPointMake(widthX/2+borderX, pointy)];
//开始画折线和后续的数值
for (int i=1; i<x; i++) {
float pointy = self.frame.size.height - [self.array[i] floatValue]/yTotalValue*height - borderY;
[linePath addLineToPoint:CGPointMake(widthX/2+widthX*i+borderX, pointy)];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(widthX/2+widthX*i+borderX, pointy, 50, 20)];
label.text = [NSString stringWithFormat:@"%ld",[self.array[i] integerValue]];
label.font = [UIFont systemFontOfSize:10];
[self addSubview:label];
}
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.lineWidth = 1;
lineLayer.strokeColor = [UIColor blackColor].CGColor;
lineLayer.path = linePath.CGPath;
lineLayer.fillColor = nil;
[self.layer addSublayer:lineLayer];
//设置动画
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 3;
pathAnimation.repeatCount = 1;
pathAnimation.removedOnCompletion = YES;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[lineLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
pathAnimation.delegate = self;
}
使用
NSArray *array = @[@(1342),@(2123),@(1654),@(1795)];
ChartView *cv = [[ChartView alloc]initWithArrayAndFrame:array andFrame:CGRectMake(0, 70, 320, 250)];
[self.view addSubview:cv];