likes
comments
collection
share

Flutter使用fl_chart的总结思考

作者站长头像
站长
· 阅读数 4
SDK版本
Flutter3.10.5
fl_chart0.61.0

最近在项目中,我们需要用折线图展示24小时内连续数据的需求,大致如下:

  1. X轴是时间轴,最长24小时,显示整点即可;Y轴显示的是正常数值;
  2. 当数据低于20,需要用灰色线条并映射区域颜色;当数值在20~40之间用绿色线条并映射区域颜色;当大于40以后使用红色线条并映射区域颜色;
  3. 支持点击查看图表上的数据点,显示详细信息;
  4. 首次展示图表最新时间的数据,即滑动到最右边;

大概图表长这样:

Flutter使用fl_chart的总结思考

在筛选了一波相关的flutter图表库后,最终选择fl_chart去实现,其示例图表中有类似的DEMO。在尝试接入过程中,遇到了一些问题:

问题思考:

  1. 在手机等小屏设备中,如果X轴有大量数据,图表需要支持水平滑动查看
  2. X轴上的时间点所在的位置都需要自己实现,而不是直接传时间数组就解决了
  3. 所有的数据在图表中的x位置也都需要根据时间点去计算位置
  4. 不同数值用不同的颜色去展示,fl_chart的颜色和渐变效果都是用百分比去实现,数据密集程度和起始时间都是影响百分比的关键因素

解决方案

一、滑动问题

  • 方案a:外套scrollview,让图表在内部滚动,需要根据数据量计算图表最大宽度
    • 优点:方便实现,易于理解
    • 弊端:体验欠佳,因为在滑至最右边时左侧的Y轴会被遮挡。可能需要额外写Y轴固定在最左侧;体验不佳
  • 方案b:在摸索过程中,发现可以通过设置minX和maxX,图表外套GestureDetector组件监听手势滑动实现,github上issue里已经有参考方案
    • 优点:滑动效果优于方案a,无需重写图表的Y轴
    • 弊端:实现难度大,边界处理

最终还是选择了方案b,目前体验下来没有遇到崩溃的问题。

二、X轴坐标问题

其实2、3点问题,不算难,只是觉得有点麻烦,本以为图表库可以轻松解决,但最终还是多了些工作量。

  • X轴上的整点需要根据接口数据动态得出所有的时间点,利用set存储整点数据
  • 接口数据的时间戳以秒为最小单位,得出在X轴上的偏移值大概思路:
    • 首先接口数据是按照时间asc排序的
    • 其次可以算出X轴上整点的set集合
    • 最后可以算出所有数据的X偏移位置,大致计算方法:(data.minute*60+data.second)/3600+{集合里的索引}。

举个例子:假如数据第一个时间点是12:30,X轴对应的第一个整点是12:00,索引就是0,那么该数据的X偏移值就是(30*60+0)/3600+0,以此类推,13点区间的数据就是索引值变成了1;

三、颜色映射问题

这个问题也是最麻烦的问题,起初在尝试使用少量切平均时间点(每10分钟一条)的数据中,未发现这个问题,我的问题方案是每条数据都在颜色数组里添加一条颜色数值,1:1的关系,多少数据就有多少个颜色数值。后面因为数据点可能在几秒钟、几十秒甚至1分钟都有可能产生,最终导致颜色映射的有问题。仔细查看官网示例,发现颜色的设定参数其实都是百分比来的,并不是1对1的关系。这个时候就要用到另外个参数stops。

在LinearGradient类中,colors数组定义了渐变中使用的颜色,而stops数组定义了这些颜色在渐变中的具体位置。如果stops是null,则假定颜色均匀分布,即颜色平均分布在渐变路径上。如果提供stops数组,它将指定每种颜色的准确位置

例如:如果传入的颜色数组是[灰色,绿色,红色],那么这3个颜色均匀显示在图表中,自灰色渐变到绿色再到红色,各占比33%左右。

stops: 定义每个颜色对应的渐变位置,必须在[0, 1]的范围内并且数组长度要和colors长度一致。

  • 例如:[0.25, 0.75] 表示灰色将开始于渐变路径的25%,而绿色将结束于渐变路径的75%。

精确计算出颜色覆盖区域,你需要考虑这些值以及它们相对于LinearGradient使用的开始和结束点的位置。

这里还有2个导致颜色映射偏差问题的因素(可以理解成本该显示绿色的线条区域显示了红色)

  1. 数据里时间戳的密集问题。这个必须依赖准确的颜色位置解决
  2. 第一条数据的起始时间。如果第一条数据刚好是12:00,那么很好,没有问题;如果是12:50,那么后面图表上的颜色映射肯定会有偏差。

同时还有一个衍生问题,如果按照官方stops的传值,你会发现颜色之间会存在个渐变混合色的产生,它并不是在颜色边界出立即由灰色变成绿色,中间会存在灰色和绿色的混合色产生,再到绿色,这导致图表看起来有点奇怪。当然如果产品不介意可忽略。

图片仅供参考: Flutter使用fl_chart的总结思考

这里我的思路就是把stops的每个边界值都给一个范围,而不是单个值绝对2个颜色的边界。

如果灰色值的占比是0~0.24999,那么数组的前2位就是[0,0.24999]
如果绿色的范围是0.25~0.75,那么数组就是[0,0.24999,0.25,0.75]
最后数组就是[0,0.24999,0.25,0.75,0.759999,1]

如果能得出上面的数组基本解决颜色渐变过程中的混色问题和颜色stops位置问题。

这里的stops里的值可以根据每条边界数据得出的x值除以最后一条数据的x值算出。

关于第一条起始时间的问题,我自己尝试过很多方式,一直没解决,我觉得问题的原因是X轴显示的长度和数据渲染的LinearGradient区域的长度偏差导致的。如果起始时间是12:50,那么12:50之前的数据都是空白的,LinearGradient区域是从12:50开始的,而X轴的起始时间是从12:00开始的,所以导致颜色的显示区间一直有偏差。

最终我的解决思路就是将12:50之前的数据给补充完整,每5分钟一条数据,值为0,颜色设置为透明,这样就解决了颜色映射偏差的问题。

记录下自己思考的过程。