iOS 使用UIBezierPath实现不等距曲线图
iOS,关于画线有很多很好的第三方,比如Charts、ECharts等等,但是我没有找到画不等距的,就自己简单的实现了一下。首先看,效果
就是描点画线加动画,没有太难的。
我自定义了一个LineChartView,和几个模型,具体demo下面会给链接
给lineChartview暴露出了几个属性和方法,都有注释
在controller里面进行初始化配置
setChartView方法
s
1 | self.chartView.y_TextFont = [UIFont systemFontOfSize:14]; |
2 | self.chartView.minValue = 0; |
3 | self.chartView.maxValue = 100; |
4 | NSArray *x_names = @[@”清醒”,@”一般”,@”黄金”]; |
5 | NSArray *xValue = @[@0,@50,@100]; |
6 | NSArray *x_colors = @[[UIColor redColor],[UIColor orangeColor],[UIColor yellowColor]]; |
7 | NSMutableArray *xAxis = [NSMutableArray new]; |
8 | for (int i = 0; i < x_names.count; i++) { |
9 | XJYAxisModel * model = [XJYAxisModel new]; |
10 | model.clolor = x_colors[i]; |
11 | model.value = xValue[i]; |
12 | model.title = x_names[i]; |
13 | [xAxis addObject:model]; |
14 | } |
15 | [self.chartView drawLineChartViewWithX_Value_Names:xAxis xCount:xCount]; |
我在controller里面定义了个方法setXAxis,用于设置x轴线上的模型具体实现
1 | – (NSArray *)setXAxis{ |
2 | // *大值和*小值 -> 每个轴线上的值 , 比如*大值90,*小值是0,10条轴线(9个间隙),则每条轴线的间距是10(0、10、20、30、40、50、60、70、80、90) |
3 | float min = 0; |
4 | float max = 90; |
5 | float space = (max – min)/(xCount – 1); |
6 | NSMutableArray *xAxisArr = [NSMutableArray new]; |
7 | for (int i = 0 ; i < xCount; i++) { |
8 | XJXAxisModel *model = [XJXAxisModel new]; |
9 | model.value = [NSNumber numberWithFloat: i * space]; |
10 | model.title = [NSString stringWithFormat:@”12:0%d”,i]; |
11 | model.clolor = [UIColor whiteColor]; |
12 | model.textFont = [UIFont systemFontOfSize:10]; |
13 | [xAxisArr addObject:model]; |
14 | } |
15 | |
16 | return xAxisArr; |
17 | } |
页面上弄了一个按钮,用于触发赋值,
1 | – (void)refreshData{ |
2 | static int a = 0; |
3 | if (a == 0) { |
4 | NSMutableArray *datas = [NSMutableArray new]; |
5 | NSArray *valueXs = @[@0,@5,@11,@19,@25,@31,@39,@43,@51,@59,@70,@85,@90]; |
6 | NSArray *valueYs = @[@0,@10,@55,@99,@88,@99,@77,@87,@10,@53,@80,@10,@0]; |
7 | for (int i = 0; i < valueXs.count; i++) { |
8 | XJDataModel *model = [XJDataModel new]; |
9 | model.xValue = valueXs[i]; |
10 | model.yValue = valueYs[i]; |
11 | [datas addObject:model]; |
12 | } |
13 | [self.chartView drawLineChartViewWithDataModels:datas withXAxisData:[self setXAxis]]; |
14 | a = 1; |
15 | }else{ |
16 | NSMutableArray *datas = [NSMutableArray new]; |
17 | NSArray *valueXs = @[@0,@5,@11,@19,@25,@31,@39,@43,@51,@59,@70,@85,@90]; |
18 | NSArray *valueYs = @[@0,@90,@55,@9,@88,@19,@77,@87,@10,@93,@80,@10,@0]; |
19 | for (int i = 0; i < valueXs.count; i++) { |
20 | XJDataModel *model = [XJDataModel new]; |
21 | model.xValue = valueXs[i]; |
22 | model.yValue = valueYs[i]; |
23 | [datas addObject:model]; |
24 | } |
25 | [self.chartView drawLineChartViewWithDataModels:datas withXAxisData:[self setXAxis]]; |
26 | a = 0; |
27 | } |
28 | } |
在画线的具体实现里面,先赋值x轴文案,然后描点画线并设置动画效果
1 | – (void)drawLineChartViewWithDataModels:(NSArray<XJDataModel *> *)datas withXAxisData:(NSArray< XJXAxisModel * >*)xAxis{ |
2 | [self reset]; |
3 | // 1. 设置x轴文案 |
4 | [self setXAxisData:xAxis]; |
5 | if (datas.count == 0) { |
6 | return; |
7 | } |
8 | // [shapeLayer removeFromSuperlayer]; |
9 | //2.获取目标值点坐标 |
10 | NSMutableArray *allPoints = [NSMutableArray array]; |
11 | for (int i = 0; i < datas.count; i++) { |
12 | XJDataModel *model = [datas objectAtIndex:i]; |
13 | float Y = y_start – scaleY * model.yValue.floatValue; |
14 | float X = x_start + scaleX * model.xValue.floatValue; |
15 | NSLog(@”X,Y = (%.2f,%.2f)”,X,Y); |
16 | CGPoint point = CGPointMake(X, Y); |
17 | [allPoints addObject:[NSValue valueWithCGPoint:point]]; |
18 | } |
19 | |
20 | // 画线 |
21 | UIBezierPath *path = [UIBezierPath bezierPath]; |
22 | [path moveToPoint:[allPoints[0] CGPointValue]]; |
23 | CGPoint PrePonit; |
24 | for (int i =0; i<allPoints.count; i++) { |
25 | if (i==0) { |
26 | PrePonit = [allPoints[0] CGPointValue]; |
27 | }else{ |
28 | CGPoint NowPoint = [allPoints[i] CGPointValue]; |
29 | [path addCurveToPoint:NowPoint controlPoint1:CGPointMake((PrePonit.x+NowPoint.x)/2, PrePonit.y) controlPoint2:CGPointMake((PrePonit.x+NowPoint.x)/2, NowPoint.y)]; //三次曲线 |
30 | PrePonit = NowPoint; |
31 | } |
32 | } |
33 | shapeLayer = [CAShapeLayer layer]; |
34 | shapeLayer.path = path.CGPath; |
35 | shapeLayer.lineWidth = 2.0; |
36 | shapeLayer.strokeColor = [UIColor orangeColor].CGColor; |
37 | shapeLayer.fillColor = [UIColor clearColor].CGColor; |
38 | shapeLayer.borderWidth = 3.0; |
39 | [self.subviews[0].layer addSublayer:shapeLayer]; |
40 | // 加动画 |
41 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@”strokeEnd”]; |
42 | animation.duration = 1.0; |
43 | animation.fromValue = @0.0f; |
44 | animation.toValue = @1.0f; |
45 | [shapeLayer addAnimation:animation forKey:@”strokeEnd”]; |
46 | for (int i = 0; i < datas.count; i++) { |
47 | CGPoint point =[allPoints[i] CGPointValue]; |
48 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(point.x-2.5, point.y-2.5, 5, 5) cornerRadius:5]; |
49 | CAShapeLayer *layer = [CAShapeLayer layer]; |
50 | layer.strokeColor = [UIColor whiteColor].CGColor; |
51 | layer.fillColor = [UIColor whiteColor].CGColor; |
52 | layer.path = path.CGPath; |
53 | [self.subviews[0].layer addSublayer:layer]; |
54 | [pointShapeLayers addObject:layer]; |
55 | } |
56 | } |