最近做项目需要画 K 线图和折线图, 引入了第三方的图标库 Charts
这个图表库基本上能够满足大家对于图表绘制的需要, 但是 api 接口的解释并不是很详细, 该库虽然有强大的功能, 但是开发者看了很长时间还是一头雾水而且网上相关的资源不是很多, 所以我写了这篇文章希望对大家有所帮助
咱们先看一下官方给出的 Demo 效果:
折线图
柱状图
K 线图
看完了效果图, 咱们逐一介绍各种图表如何绘制吧!
第一步
引入第三方图表绘制库 Charts
我用的是 Carthage 方法引入, 直接在 Cartfile 中加入
github "danielgindi/Charts"~ > 3.0.4
然后在终端命令行输入:
carthage update--platform iOS
即可
导入之后, 大家的工程项目将会包含这个文件:
由于这个框架使用 swift 语言写的, 所以 OC 开发者需要在项目中添加桥接文件, Charts-Swift 就是桥接文件, 大家不用自定义了, 想在哪个类中调用 Charts,
import "Charts-Swift.h"
文件就可以了
第二步
定义图表, 设置图标的各种属性
Charts 包含的图表类很多, 在此我举几个有代表性的例子: BarChartView(柱状图), LineChartView(折线图), CandleStickChartView(烛形图, K 线图) 等等
ChartsView 的属性:
1scale 属性
顾名思义, 就是图标是否支持拖拽,
scaleYEnabled = YES
即纵坐标支持拖拽,
scaleXEnabled = YES
即横坐标支持拖拽
2chartDescription 属性
打开这个属性, 你的图表上将会有关于你的图标的描述例如:
- chartView.chartDescription.enabled = YES
- chartView.chartDescription.text = @"王尼玛的 chartsView"
下面的这行小字
王尼玛的 chartsView
就是我的 ChartsView 的 description
3pinchZoomEnabled
是否支持 X 轴 Y 轴同时缩放, 如果是 YES , 则代表支持同时缩放
4maxVisibleCount
这个属性是控制图标上的数字展示的最大个数的, 如果你的图标不想显示上面的数字, 就可以把 maxVisibleCount 属性设置为 0
5legend
这个 Bool 属性是设置要不要显示图例的, 看到上图底部的 "-- DataSet 1" 了吗, 如果你不想要显示这一栏, 就把 legend.enabled 设置为 NO
6noDataText
没有数据的时候 ChartsView 上需要显示什么文字 chartsView 中有三个重要的属性需要开发者去设置, 那就是 leftAxis(左轴),rightAxis(右轴),xAxis(X 轴)
7doubleTapToZoomEnabled
是否允许双击缩放
8delegate
代理, 大家都懂的对应的 protocal 有 4 个, 都是可选选项
- // 图表中的数值被选中
- - (void) chartValueSelected: (ChartViewBase * _Nonnull) chartView entry: (ChartDataEntry * _Nonnull) entry highlight: (ChartHighlight * _Nonnull) highlight;
- // 图表中的空白区域被点击
- - (void) chartValueNothingSelected: (ChartViewBase * _Nonnull) chartView;
- // 图表缩放
- - (void) chartScaled: (ChartViewBase * _Nonnull) chartView scaleX: (CGFloat) scaleX scaleY: (CGFloat) scaleY;
- // 图标被移动
- - (void) chartTranslated: (ChartViewBase * _Nonnull) chartView dX: (CGFloat) dX dY: (CGFloat) dY;
Axis 属性
1enabled
设置为 NO 的话, 则对应的坐标轴不显示
2labelPosition
表示左轴坐标的位置, 有 2 个选项: YAxisLabelPositionOutsideChart = 0,YAxisLabelPositionInsideChart = 1, 坐标显示在轴内或者是轴外
3labelCount
即在坐标轴上最多显示多少个坐标点
4drawGridBackgroundEnabled
是否要画网格线
- 5gridLineDashLengths
- gridLineDashLengths = @ [@2.f, @5.f]
即线段宽为 2.0f, 空格宽为 5.0f
第三步
填充数据
定义了表格的基本属性之后我们就要填充数据了在这里我仅以折线图表为例
我们先介绍两个概念: set 和 data,LineChartData 就是折线图的 data 类, 它可以由很多组 set 组成, 一组就是一条折线因此我们可以定义 set 的属性, 从而绘制各种各样的折线示例如下:
- // 是否绘制图标
- set1.drawIconsEnabled = NO;
- // 折线颜色
- [set1 setColor: UIColor.blackColor];
- // 折线点的颜色
- [set1 setCircleColor: UIColor.blackColor];
- // 折线的宽度
- set1.lineWidth = 1.0;
- // 折线点的宽度
- set1.circleRadius = 3.0;
- // 是否画空心圆
- set1.drawCircleHoleEnabled = NO;
- // 折线点的值的大小
- set1.valueFont = [UIFont systemFontOfSize: 9.f];
- // 图例的线宽
- set1.formLineWidth = 1.0;
- // 图例的字体大小
- set1.formSize = 15.0;
下面具体介绍如何填充数据:
- // 定义一个数组承接数据
- // 对应 Y 轴上面需要显示的数据
- NSMutableArray * yVals = [[NSMutableArray alloc] init];
- for (int i = 0; i < self.financeLineDotDataList.count; i++) {
- BTCTrenddata * dotData = (BTCTrenddata * )[self.financeLineDotDataList objectAtIndex: i];
- // 将横纵坐标以 ChartDataEntry 的形式保存下来, 注意横坐标值一般是 i 的值, 而不是你的数据 // 里面具体的值, 如何将具体数据展示在 X 轴上我们下面将会说到
- ChartDataEntry * entry = [[ChartDataEntry alloc] initWithX: i y: dotData.price]; [yVals addObject: entry];
- }
- LineChartDataSet * set1 = nil;
- // 请注意这里, 如果你的图表以前绘制过, 那么这里直接重新给 data 赋值就行了
- // 如果没有, 那么要先定义 set 的属性
- if (self.financeLineChartsView.data.dataSetCount > 0) {
- LineChartData * data = (LineChartData * ) self.financeLineChartsView.data;
- set1 = (LineChartDataSet * ) data.dataSets[0];
- // set1.yVals = yVals;
- set1 = (LineChartDataSet * ) self.financeLineChartsView.data.dataSets[0];
- set1.values = yVals;
- // 通知 data 去更新
- [self.financeLineChartsView.data notifyDataChanged];
- // 通知图表去更新
- [self.financeLineChartsView notifyDataSetChanged];
- } else {
- // 创建 LineChartDataSet 对象
- set1 = [[LineChartDataSet alloc] initWithValues: yVals];
- // 自定义 set 的各种属性
- // 设置折线的样式
- set1.drawIconsEnabled = NO;
- set1.formLineWidth = 1.1; // 折线宽度
- set1.formSize = 15.0;
- set1.drawValuesEnabled = YES; // 是否在拐点处显示数据
- set1.valueColors = @ [[UIColor whiteColor]]; // 折线拐点处显示数据的颜色
- [set1 setColor: RGBCOLOR(248, 144, 28)]; // 折线颜色
- // 折线拐点样式
- set1.drawCirclesEnabled = NO; // 是否绘制拐点
- // 第二种填充样式: 渐变填充
- set1.drawFilledEnabled = YES; // 是否填充颜色
- NSArray * gradientColors = @ [(id) RGBACOLOR(218, 168, 42, 0).CGColor, (id) RGBACOLOR(248, 223, 91, 1).CGColor];
- CGGradientRef gradientRef = CGGradientCreateWithColors(nil, (CFArrayRef) gradientColors, nil);
- set1.fillAlpha = 1.0f; // 透明度
- set1.fill = [ChartFill fillWithLinearGradient: gradientRef angle: 90.0f]; // 赋值填充颜色对象
- CGGradientRelease(gradientRef); // 释放 gradientRef
- // 点击选中拐点的交互样式
- set1.highlightEnabled = YES; // 选中拐点, 是否开启高亮效果 (显示十字线)
- set1.highlightColor = RGBCOLOR(125, 125, 125); // 点击选中拐点的十字线的颜色
- set1.highlightLineWidth = 1.1 / [UIScreen mainScreen].scale; // 十字线宽度
- set1.highlightLineDashLengths = @ [@5, @5]; // 十字线的虚线样式
- // 将 LineChartDataSet 对象放入数组中
- NSMutableArray * dataSets = [[NSMutableArray alloc] init]; [dataSets addObject: set1];
- // 创建 LineChartData 对象, 此对象就是 lineChartView 需要最终数据对象
- LineChartData * data = [[LineChartData alloc] initWithDataSets: dataSets]; [data setValueFont: [UIFont systemFontOfSize: 8.f]]; // 文字字体
- [data setValueTextColor: [UIColor whiteColor]]; // 文字颜色
- self.financeLineChartsView.data = data;
- // 这里可以调用一个加载动画即 1s 出来一个绘制点
- [self.financeLineChartsView animateWithXAxisDuration: 1.0f];
- }
以上就是填充数据的基本方法到这里, 大家就已经掌握了用 charts 绘制图表的基本方法了下面我们来看一下一些比较难的用法
重难点解析
需求一: 两个表格联动, 即拖拽或者一个, 另一个需要跟着动
这个需求可以用协议解决:
- - (void)chartScaled:(ChartViewBase *)chartView scaleX:(CGFloat)scaleX scaleY:(CGFloat)scaleY {
- CGAffineTransform srcMatrix = chartView.viewPortHandler.touchMatrix;
- [self.combinedChartView.viewPortHandler refreshWithNewMatrix:srcMatrix chart:self.combinedChartView invalidate:YES];
- [self.barChartView.viewPortHandler refreshWithNewMatrix:srcMatrix chart:self.barChartView invalidate:YES];
- }
- - (void)chartTranslated:(ChartViewBase *)chartView dX:(CGFloat)dX dY:(CGFloat)dY {
- CGAffineTransform srcMatrix = chartView.viewPortHandler.touchMatrix;
- [self.combinedChartView.viewPortHandler refreshWithNewMatrix:srcMatrix chart:self.combinedChartView invalidate:YES];
- [self.barChartView.viewPortHandler refreshWithNewMatrix:srcMatrix chart:self.barChartView invalidate:YES];
- }
需求二: 在一个图表上绘制多种类型的线表, 例如 K 线图 + 柱状图
这个需求会用到另一个 ChartView 类型: CombinedChartView
- CombinedChartData * combinedData = [[CombinedChartData alloc] init];
- combinedData.lineData = [self generateLineData];
- combinedData.candleData = [self generateCandleData];
话不多说, 待会我会贴出 Demo
需求三: 希望在 X 轴上显示出具体的数值
我刚才说过, 绘制表格的时候 X 值是 i 的值, 即从 0 到 i, 那么我们如何显示服务器给我们的 X 值呢? 这里需要引入一个协议:
IChartAxisValueFormatter
, 声明一个 NSObject 类, 如
BTCDepthXAxisFormatter
遵循
IChartAxisValueFormatter
协议, 重写
- (NSString * ) stringForValue: (double) value axis: (ChartAxisBase * ) axis
方法, 然后进行赋值,
xAxis.valueFormatter = [[BTCDepthXAxisFormatter alloc] init]
即可
需求四: 在 K 线图上加上最高值和最低值的箭头指示标志, 效果如下图:
这个问题我也不清楚, 没有找到相关的 api 接口, 希望知道答案的童鞋朋友留言帮我解答哈!
至此, iOS-Charts 的基本用法就介绍完了, 如果还有不理解的问题, 可以加我的微信 (justlikeitRobert), 或者点击我在 github 上的 Demo 进行研究, 欢迎 Star, 作为对我码字的鼓励与奖赏
来源: https://juejin.im/post/5a7bcb12f265da4e9a4947b1