Flutter中的数据可视化charts家族

5,272 阅读3分钟

本文系列

  • 洋小洋周五分享
  • Flutter技术

由于在实际开发的过程中,过多的业务模块都是数据可视化,图表很多,一个模块过久的时间花费我个人觉得不太好,那目前就我来看,在Flutter家族中暂时还没有Web端像Echars这样的辅助,那本篇章就和大家分享一下线图,也叫line charts ,这其中又会分为折线图、曲线图又或者双重曲线。那接下来就当听故事一样....

003.png

故事开头

其实在图表的众多插件之中呢,就像下图所示,

001.png

开发一个插件一个包有个很完善的文档对于开发者来说是十分友好的,不过google仓库下有个图表库,是关于Flutter相关的,虽然还未有很完善的文档,但我个人觉得,它还是最值得入手的

故事过程

当我们有个需求是让用图表处理数据的话,如果UI是相对来说比较简约的,那官方维护的插件是再适合不过,然而我看也有一段时间没有更新,最新的版本依旧

  • 版本 V0.8.1

首先我们的了解这几个

其实在这个图表库中实现效果有两种方式

方式一

通过官方的示例,在调用的时候

return Container(height: height, child: SimpleLineChart.withSampleData());

通过点方法的形式,这也是示例中的使用方式,举个例子,以线图为例

/// Example of a simple line chart.
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';

class SimpleLineChart extends StatelessWidget {
  final List<charts.Series> seriesList;
  final bool animate;

  SimpleLineChart(this.seriesList, {this.animate});

  /// Creates a [LineChart] with sample data and no transition.
  factory SimpleLineChart.withSampleData() {
    return new SimpleLineChart(
      _createSampleData(),
      // Disable animations for image tests.
      animate: false,
    );
  }
  _onSelectionChanged(charts.SelectionModel model) {
    final selectedDatum = model.selectedDatum;
    print(selectedDatum.first.datum.year);
    print(selectedDatum.first.datum.sales);
    print(selectedDatum.first.series.displayName);
  }

  @override
  Widget build(BuildContext context) {
    return new charts.LineChart(
      seriesList,
      animate: animate,
      defaultRenderer: charts.LineRendererConfig(
        // 折线图绘制的配置
        includeArea: true,
        includePoints: true,
        includeLine: true,
        stacked: false,
      ),
      domainAxis: charts.NumericAxisSpec(
        // // 主轴的配置
        // tickFormatterSpec: DomainFormatterSpec(
        //     widget.dateRange), // tick 值的格式化,这里把 num 转换成 String
        renderSpec: charts.SmallTickRendererSpec(
          // 主轴绘制的配置
          tickLengthPx: 0, // 刻度标识突出的长度
          labelOffsetFromAxisPx: 12, // 刻度文字距离轴线的位移
          labelStyle: charts.TextStyleSpec(
              // 刻度文字的样式
              // color: ChartUtil.getChartColor(HColors.lightGrey),
              // fontSize: HFontSizes.smaller.toInt(),
              ),
          axisLineStyle: charts.LineStyleSpec(
              // 轴线的样式
              // color: ChartUtil.getChartColor(ChartUtil.lightBlue),
              ),
        ),
        tickProviderSpec: charts.BasicNumericTickProviderSpec(
          // 轴线刻度配置
          dataIsInWholeNumbers: false,
          // desiredTickCount: widget.data.length, // 期望显示几个刻度
        ),
      ),
      primaryMeasureAxis: charts.NumericAxisSpec(
        // 交叉轴的配置,参数参考主轴配置
        showAxisLine: false, // 显示轴线
        // tickFormatterSpec: MeasureFormatterSpec(),
        tickProviderSpec: charts.BasicNumericTickProviderSpec(
          dataIsInWholeNumbers: false,
          desiredTickCount: 4,
        ),
        renderSpec: charts.GridlineRendererSpec(
          // 交叉轴刻度水平线
          tickLengthPx: 0,
          labelOffsetFromAxisPx: 12,
          labelStyle: charts.TextStyleSpec(
              // color: ChartUtil.getChartColor(HColors.lightGrey),
              // fontSize: HFontSizes.smaller.toInt(),
              ),
          lineStyle: charts.LineStyleSpec(
              // color: ChartUtil.getChartColor(ChartUtil.lightBlue),
              ),
          axisLineStyle: charts.LineStyleSpec(
              // color: ChartUtil.getChartColor(ChartUtil.lightBlue),
              ),
        ),
      ),
      selectionModels: [
        // 设置点击选中事件
        charts.SelectionModelConfig(
          type: charts.SelectionModelType.info,
          changedListener: _onSelectionChanged,
        )
      ],
      behaviors: [
        charts.InitialSelection(selectedDataConfig: [
          // 设置默认选中
          charts.SeriesDatumConfig<num>('LineChart', 2)
        ]),
      ],
    );
  }

  /// Create one series with sample hard coded data.
  static List<charts.Series<LinearSales, int>> _createSampleData() {
    final data = [
      new LinearSales(0, 5),
      new LinearSales(1, 25),
      new LinearSales(2, 100),
      new LinearSales(3, 75),
    ];

    return [
      new charts.Series<LinearSales, int>(
        id: 'Sales',
        colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
        domainFn: (LinearSales sales, _) => sales.year,
        measureFn: (LinearSales sales, _) => sales.sales,
        data: data,
      )
    ];
  }
}

/// Sample linear data type.
class LinearSales {
  final int year;
  final int sales;

  LinearSales(this.year, this.sales);
}

以上的代码包含自定义的部分,完整我会同步到仓库传送门

方式二

这种方式就是直接传入不同图表需要的配置项就可


 Container(
            width: double.infinity,
            height: 200.0,
            child: charts.BarChart(
              //通过下面获取数据传入
              ChartFlutterBean.createSampleData(),
              //配置项,以及设置触发的函数
              selectionModels: [
                charts.SelectionModelConfig(
                  type: charts.SelectionModelType.info,
                  changedListener: _onSelectionChanged,
                )
              ],
            ),

其中比较核心的部分便是,点击事件,也就是说不管是条形图也好,这里推荐看下我的另一篇文章,也有分享到图表相关的,d点击事件就是在selectionModels 这里放着,但是我们又不能像平常写点击事件那样

006.png

我们点击去看一下源码charts.SelectionModelConfig




import 'package:meta/meta.dart' show immutable;

import 'package:charts_common/common.dart' as common;

@immutable
class SelectionModelConfig<D> {
  final common.SelectionModelType type;

  /// Listens for change in selection.
  final common.SelectionModelListener<D> changedListener;

  /// Listens anytime update selection is called.
  final common.SelectionModelListener<D> updatedListener;

  SelectionModelConfig(
      {this.type = common.SelectionModelType.info,
      this.changedListener,
      this.updatedListener});
}

我们可以看到是有两个事件的,那这时候我们也事件就可以取到值了

 _onSelectionChanged(charts.SelectionModel model) {
    final selectedDatum = model.selectedDatum;
    print(selectedDatum.first.datum.year);
    print(selectedDatum.first.datum.sales);
    print(selectedDatum.first.series.displayName);
  }

故事结尾

特别感谢你能读到这儿,今天特别开心的一事儿,

004.png

特别感谢


Although the article is here, your fate has just begun