【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});@overrideWidget 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>();@overrideWidget 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.htmldevices: {PointerDeviceKind.mouse // 鼠标 (该配置在鼠标设备时生效)},// 显示此处date相同的数据variable: 'date',),'groupMouse': PointSelection(// 触发的交互// 参考资料:https://pub.dev/documentation/keyboard_dismisser/latest/keyboard_dismisser/GestureType.htmlon: {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"相关文章:
【Flutter】graphic图表的快速上手
简介 graphic是一个数据可视化语法和Flutter图表库。 官方github示例 网上可用资源很少,只有作者的几篇文章,并且没有特别详细的文档,使用的话还是需要一定的时间去调研,在此简单记录。 示例 以折线图为例(因为我只用到了折线图,但其他的图大差不差) 创建一个两个文…...
DeepMind 推出 OPRO 技术,可用于优化 ChatGPT 提示
本心、输入输出、结果 文章目录 DeepMind 推出 OPRO 技术,可用于优化 ChatGPT 提示前言消息摘要OPRO的工作原理DeepMind的研究相关链接花有重开日,人无再少年实践是检验真理的唯一标准 DeepMind 推出 OPRO 技术,可用于优化 ChatGPT 提示 编辑…...
企业网络中的身份安全
随着近年来数字化转型的快速发展,企业使用的数字身份数量急剧增长。身份不再仅仅局限于用户。它们现在扩展到设备、应用程序、机器人、第三方供应商和组织中员工以外的其他实体。即使在用户之间,也存在不同类型的身份,例如属于IT管理员、远程…...
智能优化算法应用:基于正余弦算法无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于正余弦算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于正余弦算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.正余弦算法4.实验参数设定5.算法结果6.参考文献7.…...
创建一个带有背景图层和前景图层的渲染窗口
开发环境: Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题: 创建一个带有背景图层和前景图层的渲染窗口,知识点:1. 画布转image;2. 渲染图层设置;3.…...
Docker 运行 Oracle Autonomous Database Free Container
Docker 运行 Oracle Autonomous Database Free Container Oracle Autonomous Database Free Container Image 介绍通过 Docker 运行 Oracle Autonomous Database Free ContainerWallet 配置可用的 TNS 别名MY_ATP TNS 别名MY_ADW TNS 别名连接到 Oracle Autonomous Databas…...
《2023全球隐私计算报告》正式发布!
2023全球隐私计算报告 1、2023全球隐私计算图谱2、国内外隐私计算相关政策3、隐私计算技术的最新发展4、隐私计算技术的合规挑战5、隐私计算的应用市场动态6、隐私计算开源整体趋势7、隐私计算的未来趋势 11月23日,由浙江省人民政府、商务部共同主办,杭州…...
JAVA sql 查询2
SELECT * FROM employees order by salayr DESC SELECT employee_id,first_name,salary from employees ORDER BY salary,employee_id desc -- 最大值 最小值 总和 平均值 SELECT max(salary),MIN(salary),sum(salary),AVG(salary) FROM employees -- 总共有多少员工 select…...
为第一个原生Spring5应用程序添加上Log4J日志框架!
😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783…...
单片机复位电路
有时候我们的代码会跑飞,这个时候基本上是一切推到重来.”推倒重来”在计算机术语上称为复位.复位需要硬件的支持,复位电路就是在单片机的复位管脚上产生一个信号,俗称复位信号.这个信号需要持续一定的时间,单片机收到该信号之后就会复位,从头执行。 复位原理: 那么…...
11.28 知识回顾(Web框架、路由控制、视图层)
一、 web 框架 1.1 web框架是什么? 别人帮咱们写了一些基础代码------》我们只需要在固定的位置写固定的代码--》就能实现一个web应用 Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多…...
osgFX扩展库-异性光照、贴图、卡通特效(1)
本章将简单介绍 osgFX扩展库及osgSim 扩展库。osgFX库用得比较多,osgSim库不常用,因此,这里只对这个库作简单的说明。 osgFX扩展库 osgFX是一个OpenSceneGraph 的附加库,是一个用于实现一致、完备、可重用的特殊效果的构架工具,其…...
SELinux零知识学习三十一、SELinux策略语言之角色和用户(2)
接前一篇文章:SELinux零知识学习三十、SELinux策略语言之角色和用户(1) 三、SELinux策略语言之角色和用户 SELinux提供了一种依赖于类型强制(类型增强,TE)的基于角色的访问控制(Role-Based Access Control),角色用于组域类型和限制域类型与用户之间的关系,SELinux中…...
Unity UGUI的自动布局-LayoutGroup(水平布局)组件
Horizontal Layout Group | Unity UI | 1.0.0 1. 什么是HorizontalLayoutGroup组件? HorizontalLayoutGroup是Unity UGUI中的一种布局组件,用于在水平方向上对子物体进行排列和布局。它可以根据一定的规则自动调整子物体的位置和大小,使它们…...
【SpringCloud】设计原则之分层架构与统一通信协议
一、设计原则之分层架构 应用分层看起来很简单,但每个程序员都有自己的一套方法,哪怕是初学者,所以实施起来并非易事 最早接触的分层架构应该是最熟悉的 MVC(Model - View - Controller)架构,其将应用分成…...
在Linux环境如何启动和redis数据库?
Linux中连接redis数据库: 前台启动: 第一步:redis-server:服务器启动命令 当我们启动改窗口后,出现如下所示: 该窗口就不能关闭,否则会出现redis无法使用的情况,重新打开一个窗口,…...
selenium判断元素是否存在的方法
文章目录 快捷方法完整示例程序 快捷方法 selenium没有exist_xxx相关的方法,无法直接判断元素存在。但是锁定元素时使用的browser.find_elements(By.CSS_SELECTOR, "css元素")会返回一个列表list,如果不存在这个元素就会返回一个空列表。因此…...
后端真批量新增的使用
1,添加真批量新增抽象接口 public interface EasyBaseMapper extends BaseMapper { /** * 批量插入 仅适用于mysql * * return 影响行数 */ Integer insertBatchSomeColumn(Collection entityList); } 2,新增类,添加真批量新增的方法 public class InsertBatchSqlInjector ext…...
HttpRunner原来还能这么用,大开眼界!!!
hook机制 Httprunner 框架中的 hook 机制相当于unittest框架中的 setup , teardown 函数,用来进行测试用例执行之前的环境初始化以及测试用例执行完毕之后的环境清理操作。 httprunner 中的 hooks 机制可以用在测试用例层级也可以用在测试步骤层级,其关键…...
给WordPress 自带的搜索功能添加过滤只搜索文章的标题
如果想让 WordPress 自带的搜索功能只搜索文章标题,让搜索结果更加精确(其实WordPress 自带的搜索功能本来模糊查找就很弱),可以将下面的代码添加到当前主题functions.php中: 用过滤器:posts_search 就可以…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
