【Flutter】graphic图表的快速上手

简介

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

在这里插入图片描述
官方github示例

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

示例

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

创建一个两个文件:linePage.dart和数据文件data.dart
创建main.dart,引入linePage.dart

// 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(),
        ));
  }
}

// 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],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

数据文件

// 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"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/195738.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

运行时错误/缺陷到底是什么缺陷

运行时错误(Run-time Error)是一种跟程序运行状态相关的缺陷。这类缺陷不能通过直接禁用相关特性来屏蔽&#xff0c;而是需要通过分析变量的数值状态来发现可能的异常。简单来说&#xff0c;这些缺陷通常只有当程序执行起来以后&#xff0c;才能逐渐暴露出的缺陷&#xff0c;一…

Buzz库python代码示例

Buzz库来编写一个下载器程序。 php <?php require_once vendor/autoload.php; // 引入Buzz库 use Buzz\Browser; use Buzz\Message\Response; $browser new Browser(); // 设置 $browser->setHttpClient(new HttpClientProxy([ host > , port > , ])…

企业员工为什么不喜欢使用MES管理系统

随着科技的进步和数字化转型的趋势&#xff0c;越来越多的企业开始引入MES管理系统解决方案以提升生产效率和质量。然而&#xff0c;尽管MES管理系统的潜在优势众所周知&#xff0c;但其在企业内部的推广和应用却常常面临员工的抵触和反感。本文将从多个角度探讨企业员工为什么…

DBeaver连接MySQL提示“Public Key Retrieval is not allowed“问题解决方式

更新时间&#xff1a;2023年10月31日 11:37:53 作者&#xff1a;产品人小柒 dbeaver数据库连接工具,可以支持几乎所有的主流数据库.mysql,oracle.sqlserver,db2 等等,这篇文章主要给大家介绍了关于DBeaver连接MySQL提示"Public Key Retrieval is not allowed"问…

IDEA删除的文件怎么找回更新

一、 查找本地历史记录IDEA在进行代码版本管理时&#xff0c;会自动创建本地历史记录&#xff0c;如果我们误删了文件&#xff0c;可以通过查找本地历史记录来找回文件。 1.在项目中&#xff0c;选中被删文件的父级目录&#xff0c;“File”->“Local History”->“Show…

『VUE3后台—大事件管理系统』

项目地址&#xff1a;https://gitee.com/csheng-gitee/vue3-big-event-admin 技术栈&#xff1a;VUE3 Pinia Pnpm&#xff08;本项目暂不用 typescript&#xff09; 一、前期准备工作 1、创建项目 npm install -g pnpm pnpm create vue2、ESLint 配置 (1) 禁用 prettier 插…

java第二十章总结多线程

20.2创建线程 20.2.1继承Thread类 Thread类是Java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建议Thread实例。 public class ThreadTest extedns Thread{} run方法格式&#xff1a; public void run(){} 20.1让线程…

C语言--根据成绩判断等级

一.题目描述 如果学生的成绩小于60分&#xff0c;那么输出不及格 如果学生的成绩大于60分小于85分&#xff0c;那么输出良好 如果学生的成绩大于85分&#xff0c;那么输出优秀 二.代码实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //根据成绩打印等级 //scor…

06-学成在线添加课程,包含课程基本信息,营销信息,课程计划信息,师资信息

添加课程基本/营销/计划信息 界面原型 第一步: 用户进入课程查询列表,点击添加课程按钮,选择课程类型是直播还是录播,课程类型不同那么授课方式也不同 添加的课程和教学机构是一对一的关系 第二步: 用户选完课程形式后,点击下一步填写课程的基本信息和营销信息(两张表) 用户…

在Visual Studio Code中安装加速TypeScript程序开发的插件

在Visual Studio Code中安装加速TypeScript程序开发的插件 Install Extensions on Visual Studio Code for TypeScript Application Development By Jackson 2023-11-28 众所周知&#xff0c;微软的Visual Studio Code是一款轻量级、功能强大的集成开发环境。它支持各种编程语…

ESXi 添加虚拟闪存 无可选设备问题排查

虚拟内存是计算机系统中的一种技术&#xff0c;它可以将计算机硬盘的一部分空间作为临时存储器来使用。当计算机的物理内存&#xff08;RAM&#xff09;不足时&#xff0c;操作系统可以将部分数据从内存移至硬盘的虚拟内存空间中&#xff0c;以释放内存供其他程序使用。虚拟内存…

双通道 12V 直流电机驱动芯片GC8548,可替代LV8548/LV8549/ONSEMI,内置 LDO,不需要逻辑电源,输入 兼容 3.3V 与 5V

GC8548 是一款双通道 12V 直流电机驱动芯 片&#xff0c;为摄像机、消费类产品、玩具和其他低压或 者电池供电的运动控制类应用提供了集成的电机 驱动解决方案。芯片一般用来驱动两个直流电机 或者驱动一个步进电机。 它可以工作在 3.8~12V 的电源电压上&#xff0c; 每通道能提…

全能音乐制作环境——水果编曲软件FL Studio 21.1版本下载安装配置

目录 前言一、FL Studio 安装二、使用配置总结 前言 FL Studio是一款流行的图像线软件制作和编辑音频文件。作为一款领先的创新产品&#xff0c;该软件能够满足在创作音乐方面的需求。有了这个产品&#xff0c;可以完成制作音乐的整个过程。可以使用这个软件进行写作&#xff…

Ubuntu新手使用教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Net6.0或Net7.0项目升级到Net8.0 并 消除.Net8中SqlSugar的警告

本文基于NetCore3.1或Net6.0项目升级到Net7.0&#xff0c;参考连接&#xff1a;NetCore3.1或Net6.0项目升级到Net7.0-CSDN博客 所有项目按照此步骤操作一遍&#xff0c;完成后再将所有引用的包&#xff08;即 *.dll&#xff09;更新升级到最新版&#xff08;注意&#xff1a;有…

【软件测试面试】项目经验回答+面试技巧和方法汇总...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试面试时问你…

如何设置带有密码的excel只读模式?

Excel只读模式大家都不陌生&#xff0c;那大家知道带有密码的只读模式吗&#xff1f;今天给大家分享如何设置带有密码的只读模式。 打开excel文件&#xff0c;将文件进行【另存为】设置&#xff0c;然后停留在保存路径的界面中&#xff0c;我们点击下面的工具 – 常规选项 在常…

人机交互3——多主题多轮对话

1.主动切换 2.被动切换 3.多轮状态记忆

城市内涝积水监测系统,全方位监测城市内涝

在城市规划与防灾减灾的领域中&#xff0c;城市内涝积水监测系统的构建至关重要。随着城市化进程的加快&#xff0c;城市内涝问题日益凸显&#xff0c;对市民的生活质量和生命财产安全构成威胁。为了应对这一问题&#xff0c;建设一套高效、精准的城市内涝积水监测系统势在必行…

【开发实践】网页预览excel表格原版样式

一、需求分析 由于业务部门需要&#xff0c;在导出excel表格页面&#xff0c;不需要先下载&#xff0c;就可以直接在页面上预览该表格文件。 二、代码实现 使用Luckysheet实现&#xff1a; 什么是Luckysheet Luckysheet &#xff0c;一款纯前端类似excel的在线表格&#xff0…
最新文章