Flutter之Graphic图表的简单示例

简介

Graphic是一个数据可视化语法和Flutter图表库。


官方github示例
我的gitee示例

网上可用资源很少,只有作者的几篇文章,并且没有特别详细的文档,使用的话还是需要一定的时间去调研,在此简单记录。

示例

以折线图为例(因为我只用到了折线图,但其他的图大差不差)

创建一个两个文件:linePage.dart 和数据文件data.dart

创建main.dart ,引入linePage.dart

javascript 复制代码
// main.dart
import 'package:flutter/material.dart';
import './linePage.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Graphic Example',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Flutter Graphic Example'),
          ),
          body: linePage(),
        ));
  }
}
javascript 复制代码
// linePage.dart 
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:graphic/graphic.dart';
import 'package:intl/intl.dart';

import './data.dart';

class linePage extends StatelessWidget {
  linePage({super.key});

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Center(
        child: Column(
          children: <Widget>[
            Container(
              padding: const EdgeInsets.fromLTRB(20, 40, 20, 5),
              child: const Text(
                'Smooth Line and Area chart', //单线
                style: TextStyle(fontSize: 20),
              ),
            ),
            Container(
              margin: const EdgeInsets.only(top: 10),
              width: 350,
              height: 300,
              child: Chart(
                // 数据源
                data: invalidData,
                // 变量配置
                variables: {
                  'date': Variable(
                    accessor: (Map map) => map['date'] as String,
                    scale: OrdinalScale(
                      tickCount: 5, // x轴刻度数量
                    ),
                  ),
                  'points': Variable(
                  // 数据值
                    accessor: (Map map) => (map['points'] ?? double.nan) as num,
                  ),
                },

                marks: [
                  // 线条与X轴之间区域填充
                  AreaMark(
                    shape: ShapeEncode(
                      value:
                          BasicAreaShape(smooth: true), // smooth: true 使线条变得平滑
                    ),
                    color: ColorEncode(
                      value: Colors.pink.withAlpha(80),
                    ),
                  ),
                  // 线条
                  LineMark(
                    shape: ShapeEncode(
                      value: BasicLineShape(smooth: true),
                    ),
                    // 粗细
                    size: SizeEncode(value: 1.5),
                  ),
                ],
                // 坐标轴配置
                axes: [
                  Defaults.horizontalAxis,
                  Defaults.verticalAxis,
                ],
                /** 选项配置
                * 可以写多个,提供给tooltip单独配置selections:{'touchMove'}选择
                * 或者marks中LineMark的color属性的updaters
                */
                selections: {
                // 'touchMove'名称随意起,一般与是功能性描述词
                  'touchMove': PointSelection(
                    on: { //on里面配置操作选项
                      GestureType.scaleUpdate, // 可垂直或水平移动准线
                      GestureType.tapDown,     // 点击
                      GestureType.longPressMoveUpdate  //长按拖动
                    },
                    dim: Dim.x,
                  )
                },
                // 触摸弹框提示
                tooltip: TooltipGuide(
                  //未单独配置 selections,默认使用上面的selections中配置
                  // 跟随鼠标位置(感觉主要是看第二项是true,tooltip框才会跟随,false会随着鼠标移动乱动)
                  followPointer: [false, true],
                  align: Alignment.topLeft, // tooltip弹框对于点击位置的对齐方式
                  offset: const Offset(-20, -20), //  位置偏移量,结合align
                ),
                // 十字准线
                crosshair: CrosshairGuide(followPointer: [false, true]),
              ),
            ),
            Container(
              padding: const EdgeInsets.fromLTRB(20, 40, 20, 5),
              child: const Text(
                'Group interactions', //多线
                style: TextStyle(fontSize: 20),
              ),
            ),
            Container(
              margin: const EdgeInsets.only(top: 10),
              width: 350,
              height: 300,
              child: Chart(
                data: invalidData1,
                // 根据给定线条数据的name值相同的为同一条线
                variables: {
                  'date': Variable(
                    accessor: (Map map) => map['date'] as String,
                    scale: OrdinalScale(tickCount: 5, inflate: true),
                  ),
                  'points': Variable(
                    accessor: (Map map) => (map['points'] ?? double.nan) as num,
                  ),
                  'name': Variable(
                    accessor: (Map map) => map['name'] as String,
                  ),
                },
                coord: RectCoord(horizontalRange: [0.1, 0.99]),
                marks: [
                  LineMark(
                    position:
                        Varset('date') * Varset('points') / Varset('name'),
                    shape: ShapeEncode(value: BasicLineShape(smooth: true)),
                    size: SizeEncode(value: 1.5),
                    color: ColorEncode(
                      variable: 'name',
                      values: Defaults.colors10,
                      // 改变线条颜色
                      // updaters: {
                      // 'groupMouse'是在selections中配置的
                      //   'groupMouse': {false: (color) => color.withAlpha(100)},
                      //   // 'groupTouch': {false: (color) => color.withAlpha(100)},
                      // },
                    ),
                  ),
                  // 显示线条上的数据点
                  // PointMark(
                  //   color: ColorEncode(
                  //     variable: 'name',
                  //     values: Defaults.colors10,
                  //     updaters: {
                  //       'groupMouse': {false: (color) => color.withAlpha(100)},
                  //       'groupTouch': {false: (color) => color.withAlpha(100)},
                  //     },
                  //   ),
                  // ),
                ],
                axes: [
                  Defaults.horizontalAxis,
                  Defaults.verticalAxis,
                ],
                // // 提示框选项配置
                selections: {
                  '666': PointSelection(
                    on: {GestureType.hover, GestureType.tap},
                    // 设备[mouse(鼠标),stylus(手写笔),invertedStylus,trackpad(触控板),touch(触摸屏),unknown]
                    // 参考资料:https://api.flutter.dev/flutter/dart-ui/PointerDeviceKind.html
                    devices: {
                    	PointerDeviceKind.mouse // 鼠标 (该配置在鼠标设备时生效)
                    },
                    // 显示此处date相同的数据
                    variable: 'date',
                  ),
                  'groupMouse': PointSelection(
                  	// 触发的交互
                  	// 参考资料:https://pub.dev/documentation/keyboard_dismisser/latest/keyboard_dismisser/GestureType.html
                    on: {
                      GestureType.hover, // 覆盖
                    },
                    // variable: 'name',
                    devices: {PointerDeviceKind.mouse},
                  ),
                  'tooltipTouch': PointSelection(
                    on: {
                      GestureType.scaleUpdate, 
                      GestureType.tapDown, //点击
                      GestureType.longPressMoveUpdate 
                    },
                    // variable: 'name',
                    devices: {
                    	PointerDeviceKind.touch,  // 触摸屏(仅在触摸设备生效:神奇的是不包括iOS)
                    },
                  ),
                  'tooltipTouchIos': PointSelection(
                    on: {
                      GestureType.scaleUpdate,
                      GestureType.tapDown,
                      GestureType.longPressMoveUpdate
                    },
                    // variable: 'name',
                    devices: {
                    	// 未知设备(不明白为啥iOS被识别成了unknown,猜测可能与ios中的触摸事件有关)
                    	PointerDeviceKind.unknown, 
                    },
                  ),
                },
                tooltip: TooltipGuide(
                  // 选择触发配置
                  selections: {'tooltipTouch', '666'},
                  followPointer: [false, true],
                  align: Alignment.topLeft,
                  // tooltip中显示的内容(按顺序显示)
                  // 与上方selections中定义的variable相排斥
                  variables: [
                    // 'date',
                    'name',
                    'points',
                  ],
                ),
                // 十字准线配置
                crosshair: CrosshairGuide(
                  selections: {'tooltipTouch', '666'},
                  styles: [
                    PaintStyle(
                        strokeColor: const Color.fromARGB(255, 92, 68, 68)),
                    PaintStyle(
                        strokeColor: const Color.fromARGB(0, 158, 154, 154)),
                  ],
                  followPointer: [false, true],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

数据文件

dart 复制代码
// data.dart
const invalidData1 = [
  {"date": "2016-01-04", "name": "线条1", "points": 126.12},
  {"date": "2016-01-05", "name": "线条1", "points": 125.688},
  {"date": "2016-01-06", "name": "线条1", "points": 119.704},
  {"date": "2016-01-07", "name": "线条1", "points": 120.19},
  {"date": "2016-01-08", "name": "线条1", "points": 121.157},
  {"date": "2016-01-11", "name": "线条1", "points": 117},
  {"date": "2016-01-12", "name": "线条1", "points": 120},
  {"date": "2016-01-13", "name": "线条1", "points": 122},
  {"date": "2016-01-14", "name": "线条1", "points": 117.76},
  {"date": "2016-01-15", "name": "线条1", "points": 114.397},
  {"date": "2016-01-18", "name": "线条1", "points": 116.373},
  {"date": "2016-01-19", "name": "线条1", "points": 120.547},
  {"date": "2016-01-20", "name": "线条1", "points": 113.733},
  {"date": "2016-01-21", "name": "线条1", "points": 114.098},
  {"date": "2016-01-22", "name": "线条1", "points": 123.833},
  {"date": "2016-01-25", "name": "线条1", "points": 125},
  {"date": "2016-01-26", "name": "线条1", "points": 124.866},
  {"date": "2016-01-27", "name": "线条1", "points": 120.264},
  {"date": "2016-01-28", "name": "线条1", "points": 122.296},
  {"date": "2016-01-29", "name": "线条1", "points": 124.502},
  {"date": "2016-02-01", "name": "线条1", "points": 127.936},
  {"date": "2016-02-02", "name": "线条1", "points": null},
  {"date": "2016-02-03", "name": "线条1", "points": 129.95},
  {"date": "2016-02-04", "name": "线条1", "points": 129.275},
  {"date": "2016-02-05", "name": "线条1", "points": 127.898},
  {"date": "2016-02-08", "name": "线条1", "points": 134.9},
  {"date": "2016-02-09", "name": "线条1", "points": 122.819},
  {"date": "2016-02-10", "name": "线条1", "points": 120.108},
  {"date": "2016-02-11", "name": "线条1", "points": 119.447},
  {"date": "2016-02-12", "name": "线条1", "points": 117.8},
  {"date": "2016-02-15", "name": "线条1", "points": null},
  {"date": "2016-02-16", "name": "线条1", "points": 121.865},
  {"date": "2016-02-17", "name": "线条1", "points": 126.3},
  {"date": "2016-02-18", "name": "线条1", "points": 128.259},
  {"date": "2016-02-19", "name": "线条1", "points": 125.724},
  {"date": "2016-02-22", "name": "线条1", "points": 130},
  {"date": "2016-02-23", "name": "线条1", "points": 129.948},
  {"date": "2016-02-24", "name": "线条1", "points": 132.5},
  {"date": "2016-02-25", "name": "线条1", "points": 128.08},
  {"date": "2016-02-26", "name": "线条1", "points": 122},
  {"date": "2016-02-29", "name": "线条1", "points": 122},
  {"date": "2016-03-01", "name": "线条1", "points": 123.449},
  {"date": "2016-03-02", "name": "线条1", "points": double.nan},
  {"date": "2016-03-03", "name": "线条1", "points": 132},
  {"date": "2016-03-04", "name": "线条1", "points": 135},
  {"date": "2016-03-07", "name": "线条1", "points": 123.905},
  {"date": "2016-03-08", "name": "线条1", "points": 125.155},
  {"date": "2016-03-09", "name": "线条1", "points": 126},
  {"date": "2016-03-10", "name": "线条1", "points": 126.778},
  {"date": "2016-03-11", "name": "线条1", "points": 129.656},
  {"date": "2016-03-14", "name": "线条1", "points": 127.64},
  {"date": "2016-03-15", "name": "线条1", "points": 124.786},
  {"date": "2016-03-16", "name": "线条1", "points": 124.469},
  {"date": "2016-03-17", "name": "线条1", "points": 123.5},
  {"date": "2016-03-18", "name": "线条1", "points": 124.061},
  {"date": "2016-03-21", "name": "线条1", "points": 123.5},
  {"date": "2016-03-22", "name": "线条1", "points": 129.002},
  {"date": "2016-03-23", "name": "线条1", "points": 129},
  {"date": "2016-03-24", "name": "线条1", "points": 131.31},
  {"date": "2016-03-29", "name": "线条1", "points": 133},
  {"date": "2016-03-30", "name": "线条1", "points": 129.298},
  {"date": "2016-03-31", "name": "线条1", "points": 127.4},
  {"date": "2016-04-01", "name": "线条1", "points": 122.376},
  {"date": "2016-04-04", "name": "线条1", "points": 119.467},
  {"date": "2016-04-05", "name": "线条1", "points": 120.695},
  {"date": "2016-04-06", "name": "线条1", "points": 118.725},
  {"date": "2016-04-07", "name": "线条1", "points": 127.539},
  {"date": "2016-04-08", "name": "线条1", "points": 129.8},
  {"date": "2016-04-11", "name": "线条1", "points": 129.5},
  {"date": "2016-04-12", "name": "线条1", "points": 134.465},
  {"date": "2016-04-13", "name": "线条1", "points": 133},
  {"date": "2016-04-14", "name": "线条1", "points": 137.35},
  {"date": "2016-04-15", "name": "线条1", "points": 137.2},
  {"date": "2016-04-18", "name": "线条1", "points": 132.611},
  {"date": "2016-04-19", "name": "线条1", "points": 135.479},
  {"date": "2016-04-20", "name": "线条1", "points": 139.05},
  {"date": "2016-04-21", "name": "线条1", "points": 142},
  {"date": "2016-04-22", "name": "线条1", "points": 135.761},
  {"date": "2016-04-25", "name": "线条1", "points": 136.174},
  {"date": "2016-04-26", "name": "线条1", "points": 134.782},
  {"date": "2016-04-27", "name": "线条1", "points": 128},
  {"date": "2016-04-28", "name": "线条1", "points": 121.5},
  {"date": "2016-04-29", "name": "线条1", "points": 120},
  {"date": "2016-05-02", "name": "线条1", "points": 123.966},
  {"date": "2016-05-03", "name": "线条1", "points": 122.538},
  {"date": "2016-05-04", "name": "线条1", "points": 120},
  {"date": "2016-05-05", "name": "线条1", "points": 120.21},
  {"date": "2016-05-06", "name": "线条1", "points": 121.01},
  {"date": "2016-05-09", "name": "线条1", "points": double.nan},
  {"date": "2016-05-10", "name": "线条1", "points": 120.622},
  {"date": "2016-05-11", "name": "线条1", "points": 123.85},
  {"date": "2016-05-12", "name": "线条1", "points": 122.963},
  {"date": "2016-05-13", "name": "线条1", "points": 126},
  {"date": "2016-05-17", "name": "线条1", "points": 130},
  {"date": "2016-05-18", "name": "线条1", "points": 128.845},
  {"date": "2016-05-19", "name": "线条1", "points": 130.17},
  {"date": "2016-05-20", "name": "线条1", "points": 129.741},
  {"date": "2016-05-23", "name": "线条1", "points": 129.668},
  {"date": "2016-05-24", "name": "线条1", "points": 126.886},
  {"date": "2016-05-25", "name": "线条1", "points": 128.239},
  {"date": "2016-05-26", "name": "线条1", "points": 127.239},
  {"date": "2016-05-27", "name": "线条1", "points": 127.457},
  {"date": "2016-05-30", "name": "线条1", "points": 127.37},
  {"date": "2016-05-31", "name": "线条1", "points": 130.756},
  {"date": "2016-06-01", "name": "线条1", "points": 133.232},
  {"date": "2016-06-02", "name": "线条1", "points": 126.47},
  {"date": "2016-06-03", "name": "线条1", "points": 126.385},
  {"date": "2016-06-06", "name": "线条1", "points": 128.331},
  {"date": "2016-06-07", "name": "线条1", "points": 130.914},
  {"date": "2016-06-08", "name": "线条1", "points": 133},
  {"date": "2016-06-09", "name": "线条1", "points": 133.041},
  {"date": "2016-06-10", "name": "线条1", "points": 133.041},
  {"date": "2016-06-13", "name": "线条1", "points": 129},
  {"date": "2016-06-14", "name": "线条1", "points": 129.166},
  {"date": "2016-06-15", "name": "线条1", "points": 124.687},
  {"date": "2016-06-16", "name": "线条1", "points": 122.77},
  {"date": "2016-06-17", "name": "线条1", "points": 126.461},
  {"date": "2016-06-20", "name": "线条1", "points": 127},
  {"date": "2016-06-21", "name": "线条1", "points": 125.594},
  {"date": "2016-06-22", "name": "线条1", "points": 127.438},
  {"date": "2016-06-23", "name": "线条1", "points": 124.44},
  {"date": "2016-06-24", "name": "线条1", "points": 122.131},
  {"date": "2016-06-27", "name": "线条1", "points": 120.53},
  {"date": "2016-06-28", "name": "线条1", "points": 120.296},
  {"date": "2016-06-29", "name": "线条1", "points": 125.877},
  {"date": "2016-06-30", "name": "线条1", "points": 126.404},
  {"date": "2016-01-04", "name": "线条2", "points": 130.914},
  {"date": "2016-01-05", "name": "线条2", "points": 133},
  {"date": "2016-01-06", "name": "线条2", "points": 159.704},
  {"date": "2016-01-07", "name": "线条2", "points": 133.19},
  {"date": "2016-01-08", "name": "线条2", "points": 202.157},
  {"date": "2016-01-11", "name": "线条2", "points": 128},
  {"date": "2016-01-12", "name": "线条2", "points": 138},
  {"date": "2016-01-13", "name": "线条2", "points": 152},
  {"date": "2016-01-14", "name": "线条2", "points": 157.76},
  {"date": "2016-01-15", "name": "线条2", "points": 134.397},
  {"date": "2016-01-18", "name": "线条2", "points": 170.373},
  {"date": "2016-01-19", "name": "线条2", "points": 140.547},
  {"date": "2016-01-20", "name": "线条2", "points": 133.733},
  {"date": "2016-01-21", "name": "线条2", "points": 124.098},
  {"date": "2016-01-22", "name": "线条2", "points": 113.833},
  {"date": "2016-01-25", "name": "线条2", "points": 125},
  {"date": "2016-01-26", "name": "线条2", "points": 154.866},
  {"date": "2016-01-27", "name": "线条2", "points": 130.264},
  {"date": "2016-01-28", "name": "线条2", "points": 142.296},
  {"date": "2016-01-29", "name": "线条2", "points": 114.502},
  {"date": "2016-02-01", "name": "线条2", "points": 137.936},
  {"date": "2016-02-02", "name": "线条2", "points": null},
  {"date": "2016-02-03", "name": "线条2", "points": 169.95},
  {"date": "2016-02-04", "name": "线条2", "points": 119.275},
  {"date": "2016-02-05", "name": "线条2", "points": 127.898},
  {"date": "2016-02-08", "name": "线条2", "points": 134.9},
  {"date": "2016-02-09", "name": "线条2", "points": 152.819},
  {"date": "2016-02-10", "name": "线条2", "points": 100.108},
  {"date": "2016-02-11", "name": "线条2", "points": 109.447},
  {"date": "2016-02-12", "name": "线条2", "points": 127.8},
  {"date": "2016-02-15", "name": "线条2", "points": null},
  {"date": "2016-02-22", "name": "线条2", "points": 120},
  {"date": "2016-02-23", "name": "线条2", "points": 149.948},
  {"date": "2016-02-24", "name": "线条2", "points": 102.5},
  {"date": "2016-03-03", "name": "线条2", "points": 142},
  {"date": "2016-03-04", "name": "线条2", "points": 165},
  {"date": "2016-03-07", "name": "线条2", "points": 173.905},
  {"date": "2016-03-08", "name": "线条2", "points": 128.155},
  {"date": "2016-02-25", "name": "线条2", "points": 118.08},
  {"date": "2016-04-04", "name": "线条2", "points": 149.467},
  {"date": "2016-04-05", "name": "线条2", "points": 130.695},
  {"date": "2016-04-06", "name": "线条2", "points": 128.725},
  {"date": "2016-04-07", "name": "线条2", "points": 137.539},
  {"date": "2016-04-08", "name": "线条2", "points": 135.8},
  {"date": "2016-04-11", "name": "线条2", "points": 138.5},
  {"date": "2016-04-12", "name": "线条2", "points": 124.465},
  {"date": "2016-04-13", "name": "线条2", "points": 143},
  {"date": "2016-04-14", "name": "线条2", "points": 134.35},
  {"date": "2016-04-15", "name": "线条2", "points": 127.2},
  {"date": "2016-04-18", "name": "线条2", "points": 112.611},
  {"date": "2016-04-19", "name": "线条2", "points": 135.479},
  {"date": "2016-02-26", "name": "线条2", "points": 142},
  {"date": "2016-02-29", "name": "线条2", "points": 132},
  {"date": "2016-03-01", "name": "线条2", "points": 113.449},
  {"date": "2016-03-02", "name": "线条2", "points": double.nan},
  {"date": "2016-02-16", "name": "线条2", "points": 131.865},
  {"date": "2016-02-17", "name": "线条2", "points": 156.3},
  {"date": "2016-02-18", "name": "线条2", "points": 148.259},
  {"date": "2016-02-19", "name": "线条2", "points": 135.724},
  {"date": "2016-03-09", "name": "线条2", "points": 116},
  {"date": "2016-03-10", "name": "线条2", "points": 176.778},
  {"date": "2016-03-11", "name": "线条2", "points": 139.656},
  {"date": "2016-03-14", "name": "线条2", "points": 157.64},
  {"date": "2016-03-15", "name": "线条2", "points": double.nan},
  {"date": "2016-03-16", "name": "线条2", "points": 144.469},
  {"date": "2016-03-17", "name": "线条2", "points": 133.5},
  {"date": "2016-03-18", "name": "线条2", "points": 184.061},
  {"date": "2016-03-21", "name": "线条2", "points": 163.5},
  {"date": "2016-03-22", "name": "线条2", "points": 159.002},
  {"date": "2016-03-23", "name": "线条2", "points": 149},
  {"date": "2016-03-24", "name": "线条2", "points": 111.31},
  {"date": "2016-03-29", "name": "线条2", "points": 123},
  {"date": "2016-03-30", "name": "线条2", "points": 139.298},
  {"date": "2016-03-31", "name": "线条2", "points": 147.4},
  {"date": "2016-04-01", "name": "线条2", "points": 132.376},
  {"date": "2016-04-20", "name": "线条2", "points": 149.05},
  {"date": "2016-04-21", "name": "线条2", "points": 162},
  {"date": "2016-04-22", "name": "线条2", "points": 155.761},
  {"date": "2016-04-25", "name": "线条2", "points": 126.174},
  {"date": "2016-04-26", "name": "线条2", "points": 134.782},
  {"date": "2016-04-27", "name": "线条2", "points": 118},
  {"date": "2016-04-28", "name": "线条2", "points": 141.5},
  {"date": "2016-05-31", "name": "线条2", "points": 130.756},
  {"date": "2016-06-01", "name": "线条2", "points": 143.232},
  {"date": "2016-06-02", "name": "线条2", "points": 176.47},
  {"date": "2016-06-03", "name": "线条2", "points": 156.385},
  {"date": "2016-06-06", "name": "线条2", "points": 168.331},
  {"date": "2016-06-07", "name": "线条2", "points": 130.914},
  {"date": "2016-06-08", "name": "线条2", "points": 123},
  {"date": "2016-06-09", "name": "线条2", "points": 133.041},
  {"date": "2016-06-10", "name": "线条2", "points": 133.041},
  {"date": "2016-06-13", "name": "线条2", "points": 129},
  {"date": "2016-06-14", "name": "线条2", "points": null},
  {"date": "2016-06-15", "name": "线条2", "points": 114.687},
  {"date": "2016-06-16", "name": "线条2", "points": 122.77},
  {"date": "2016-06-17", "name": "线条2", "points": 146.461},
  {"date": "2016-06-20", "name": "线条2", "points": 127},
  {"date": "2016-06-21", "name": "线条2", "points": 155.594},
  {"date": "2016-06-22", "name": "线条2", "points": 127.438},
  {"date": "2016-06-23", "name": "线条2", "points": 134.44},
  {"date": "2016-06-24", "name": "线条2", "points": 112.131},
  {"date": "2016-06-27", "name": "线条2", "points": 100.53},
  {"date": "2016-06-28", "name": "线条2", "points": 150.296},
  {"date": "2016-06-29", "name": "线条2", "points": 135.877},
  {"date": "2016-06-30", "name": "线条2", "points": 126.404},
  {"date": "2016-04-29", "name": "线条2", "points": 130},
  {"date": "2016-05-02", "name": "线条2", "points": 123.966},
  {"date": "2016-05-03", "name": "线条2", "points": 122.538},
  {"date": "2016-05-04", "name": "线条2", "points": 130},
  {"date": "2016-05-05", "name": "线条2", "points": 120.21},
  {"date": "2016-05-06", "name": "线条2", "points": 131.01},
  {"date": "2016-05-09", "name": "线条2", "points": double.nan},
  {"date": "2016-05-10", "name": "线条2", "points": 120.622},
  {"date": "2016-05-11", "name": "线条2", "points": 153.85},
  {"date": "2016-05-12", "name": "线条2", "points": 162.963},
  {"date": "2016-05-13", "name": "线条2", "points": 146},
  {"date": "2016-05-17", "name": "线条2", "points": 130},
  {"date": "2016-05-18", "name": "线条2", "points": 138.845},
  {"date": "2016-05-19", "name": "线条2", "points": 120.17},
  {"date": "2016-05-20", "name": "线条2", "points": 149.741},
  {"date": "2016-05-23", "name": "线条2", "points": 119.668},
  {"date": "2016-05-24", "name": "线条2", "points": 136.886},
  {"date": "2016-05-25", "name": "线条2", "points": 108.239},
  {"date": "2016-05-26", "name": "线条2", "points": 147.239},
  {"date": "2016-05-27", "name": "线条2", "points": 127.457},
  {"date": "2016-05-30", "name": "线条2", "points": 137.37},
];

const invalidData = [
  {"date": "2016-01-04", "points": 126.12},
  {"date": "2016-01-05", "points": 125.688},
  {"date": "2016-01-06", "points": 119.704},
  {"date": "2016-01-07", "points": 120.19},
  {"date": "2016-01-08", "points": 121.157},
  {"date": "2016-01-11", "points": 117},
  {"date": "2016-01-12", "points": 120},
  {"date": "2016-01-13", "points": 122},
  {"date": "2016-01-14", "points": 117.76},
  {"date": "2016-01-15", "points": 114.397},
  {"date": "2016-01-18", "points": 116.373},
  {"date": "2016-01-19", "points": 120.547},
  {"date": "2016-01-20", "points": 113.733},
  {"date": "2016-01-21", "points": 114.098},
  {"date": "2016-01-22", "points": 123.833},
  {"date": "2016-01-25", "points": 125},
  {"date": "2016-01-26", "points": 124.866},
  {"date": "2016-01-27", "points": 120.264},
  {"date": "2016-01-28", "points": 122.296},
  {"date": "2016-01-29", "points": 124.502},
  {"date": "2016-02-01", "points": 127.936},
  {"date": "2016-02-02", "points": null},
  {"date": "2016-02-03", "points": 129.95},
  {"date": "2016-02-04", "points": 129.275},
  {"date": "2016-02-05", "points": 127.898},
  {"date": "2016-02-08", "points": 134.9},
  {"date": "2016-02-09", "points": 122.819},
  {"date": "2016-02-10", "points": 120.108},
  {"date": "2016-02-11", "points": 119.447},
  {"date": "2016-02-12", "points": 117.8},
  {"date": "2016-02-15", "points": null},
  {"date": "2016-02-16", "points": 121.865},
  {"date": "2016-02-17", "points": 126.3},
  {"date": "2016-02-18", "points": 128.259},
  {"date": "2016-02-19", "points": 125.724},
  {"date": "2016-02-22", "points": 130},
  {"date": "2016-02-23", "points": 129.948},
  {"date": "2016-02-24", "points": 132.5},
  {"date": "2016-02-25", "points": 128.08},
  {"date": "2016-02-26", "points": 122},
  {"date": "2016-02-29", "points": 122},
  {"date": "2016-03-01", "points": 123.449},
  {"date": "2016-03-02", "points": double.nan},
  {"date": "2016-03-03", "points": 132},
  {"date": "2016-03-04", "points": 135},
  {"date": "2016-03-07", "points": 123.905},
  {"date": "2016-03-08", "points": 125.155},
  {"date": "2016-03-09", "points": 126},
  {"date": "2016-03-10", "points": 126.778},
  {"date": "2016-03-11", "points": 129.656},
  {"date": "2016-03-14", "points": 127.64},
  {"date": "2016-03-15", "points": 124.786},
  {"date": "2016-03-16", "points": 124.469},
  {"date": "2016-03-17", "points": 123.5},
  {"date": "2016-03-18", "points": 124.061},
  {"date": "2016-03-21", "points": 123.5},
  {"date": "2016-03-22", "points": 129.002},
  {"date": "2016-03-23", "points": 129},
  {"date": "2016-03-24", "points": 131.31},
  {"date": "2016-03-29", "points": 133},
  {"date": "2016-03-30", "points": 129.298},
  {"date": "2016-03-31", "points": 127.4},
  {"date": "2016-04-01", "points": 122.376},
  {"date": "2016-04-04", "points": 119.467},
  {"date": "2016-04-05", "points": 120.695},
  {"date": "2016-04-06", "points": 118.725},
  {"date": "2016-04-07", "points": 127.539},
  {"date": "2016-04-08", "points": 129.8},
  {"date": "2016-04-11", "points": 129.5},
  {"date": "2016-04-12", "points": 134.465},
  {"date": "2016-04-13", "points": 133},
  {"date": "2016-04-14", "points": 137.35},
  {"date": "2016-04-15", "points": 137.2},
  {"date": "2016-04-18", "points": 132.611},
  {"date": "2016-04-19", "points": 135.479},
  {"date": "2016-04-20", "points": 139.05},
  {"date": "2016-04-21", "points": 142},
  {"date": "2016-04-22", "points": 135.761},
  {"date": "2016-04-25", "points": 136.174},
  {"date": "2016-04-26", "points": 134.782},
  {"date": "2016-04-27", "points": 128},
  {"date": "2016-04-28", "points": 121.5},
  {"date": "2016-04-29", "points": 120},
  {"date": "2016-05-02", "points": 123.966},
  {"date": "2016-05-03", "points": 122.538},
  {"date": "2016-05-04", "points": 120},
  {"date": "2016-05-05", "points": 120.21},
  {"date": "2016-05-06", "points": 121.01},
  {"date": "2016-05-09", "points": double.nan},
  {"date": "2016-05-10", "points": 120.622},
  {"date": "2016-05-11", "points": 123.85},
  {"date": "2016-05-12", "points": 122.963},
  {"date": "2016-05-13", "points": 126},
  {"date": "2016-05-17", "points": 130},
  {"date": "2016-05-18", "points": 128.845},
  {"date": "2016-05-19", "points": 130.17},
  {"date": "2016-05-20", "points": 129.741},
  {"date": "2016-05-23", "points": 129.668},
  {"date": "2016-05-24", "points": 126.886},
  {"date": "2016-05-25", "points": 128.239},
  {"date": "2016-05-26", "points": 127.239},
  {"date": "2016-05-27", "points": 127.457},
  {"date": "2016-05-30", "points": 127.37},
  {"date": "2016-05-31", "points": 130.756},
  {"date": "2016-06-01", "points": 133.232},
  {"date": "2016-06-02", "points": 126.47},
  {"date": "2016-06-03", "points": 126.385},
  {"date": "2016-06-06", "points": 128.331},
  {"date": "2016-06-07", "points": 130.914},
  {"date": "2016-06-08", "points": 133},
  {"date": "2016-06-09", "points": 133.041},
  {"date": "2016-06-10", "points": 133.041},
  {"date": "2016-06-13", "points": 129},
  {"date": "2016-06-14", "points": 129.166},
  {"date": "2016-06-15", "points": 124.687},
  {"date": "2016-06-16", "points": 122.77},
  {"date": "2016-06-17", "points": 126.461},
  {"date": "2016-06-20", "points": 127},
  {"date": "2016-06-21", "points": 125.594},
  {"date": "2016-06-22", "points": 127.438},
  {"date": "2016-06-23", "points": 124.44},
  {"date": "2016-06-24", "points": 122.131},
  {"date": "2016-06-27", "points": 120.53},
  {"date": "2016-06-28", "points": 120.296},
  {"date": "2016-06-29", "points": 125.877},
  {"date": "2016-06-30", "points": 126.404},
];

效果

参考资料

  1. 官方github
  2. 作者博客
  3. selections中on参数
  4. selections中设备参数
相关推荐
恋猫de小郭5 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
明君8799710 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter
四眼肥鱼17 小时前
flutter 利用flutter_libserialport 实现SQ800 串口通信
前端·flutter
火柴就是我1 天前
让我们实现一个更好看的内部阴影按钮
android·flutter
王晓枫1 天前
flutter接入三方库运行报错:Error running pod install
前端·flutter
shankss2 天前
Flutter 下拉刷新库 pull_to_refresh_plus 设计与实现分析
flutter
忆江南2 天前
iOS 深度解析
flutter·ios
明君879972 天前
Flutter 实现 AI 聊天页面 —— 记一次 Markdown 数学公式显示的踩坑之旅
前端·flutter
恋猫de小郭2 天前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
MakeZero3 天前
Flutter那些事-交互式组件
flutter