node_graph (0.0.1)

Published 2024-03-26 15:30:33 +08:00 by YuanJunYao

Installation

dart pub add node_graph:0.0.1 --hosted-url=

About this package

绘制一对多节点图

绘制一对多节点图

cd ./example
flutter run example.dart

用法

用组件显示节点

void main() {
  // 创建根节点
  final node = Node(data: 'root');

  // 扩展节点数据
  // node.expandData(['a', 'b', 'c']);
  // ...
  final widget = NodeGraphView(
    root,
  );
}

计算节点布局,不推荐直接计算

// 创建根节点
final node = Node(data: 'root');

// 扩展节点数据
// node.expandData(['a', 'b', 'c']);
// ...

// 对节点进行布局
final laidOutNode = node.layout();

算法总览

先从叶子往上测量,后从根节点往下布局

测量

从父节点开始一直迭代到叶子节点,让子节点都向父节点返回测量结果。

如果子节点是叶子节点,把节点的大小计算即可,

如果子节点还有子节点,那么让子节点计算其自己的大小

节点子节点有子节点时: 获取每个子节点的大小(是一个矩形区域),把多个子节点的矩形区域区域,环绕节点一圈,然后计算节点 + 环绕的子节点区域,组成的矩形区域,返回给父节点计算

以上是测量步骤的迭代过程,因为用了矩形区域来限定子节点的位置,所以节点永不重叠

测量结果包括:

  1. 每一级中,节点和子节点的距离
  2. 每一级中,子节点的的角度
  3. 每一级中,基于当前节点为(0, 0),节点和子节点所占的区域

布局

给定一个根节点开始布局的位置,按之前测量的结果,往下布局

渲染和计算讨论

位置计算

可预料到这种算法在大量的数据下,会非常耗费性能,需要优化

情况分析:

  1. 算法的输入是节点结构,输出是节点的坐标,输入输出数据量不大。结论:不需要把性能耗费在序列化上,所以可很效率地使用dart isolate
  2. 节点的计算不需要实时性,用户扩展节点后,可等待一段时间再看到节点展开。结论:可以让dart isolate在背后计算,然后主isolate优先处理界面显示,显示优先

创建一个专门计算节点位置的isolate,它不停输出节点的位置,界面根据这些位置进行显示,甚至做动画效果

大量节点的渲染

利用缓存

如果节点图形很复杂,我们可以利用缓存

利用缩放特性

遵循以下规则

  1. 当节点在屏幕外部,不渲染(如果有算法可以输入region迅速找到对应节点更好,如google s2算法)
  2. 不能无限制缩小节点图

然后根据三种缩放倍率,节点会有显示方式和效果的不同

能力/倍率
绘制模式 canvas canvas Widget
可否动画 否,一次渲染成图片
样式 单一几何形状 复杂形状 可任意复杂组件
是否随机浮动
节点扩展动画
是否可交互

由于我们现在能精确计算节点的位置,所以对于canvas和Widget的绘制形式可用动画做到无缝切换

开发计划

  • 设计布局算法,相同的节点结构输入,就有相同的位置输出,且不重叠,
  • 目前优化对于空间利用不高,需要优化
    • 用子节点矩形中高最大的矩形计算节点到子节点距离改为*用每一个矩形高,在分配的角度下,计算半径
    • 计算节点和子节点的矩形区域盒子时,应当计算子节点矩形区域内的节点,而不是只计算矩形区域
  • 在单独的isolate计算节点位置
    • isolate在接收到节点结构后,计算节点位置信息,向主isolate刷新节点位置信息
    • isolate接收主isolate发送的命令,如展开节点等,isolate向主isolate刷新节点位置信息
  • 封装Widget组件显示节点位置,绘制连线
  • 不同倍率下不同的节点绘制方式
    • 绘制方式
      • Canvas绘制节点
      • Widget显示节点
    • 随机移动
    • 节点扩展动画
Details
Pub
2024-03-26 15:30:33 +08:00
19
274 KiB
Assets (1)
0.0.1.tar.gz 274 KiB
Versions (1) View all
0.0.1 2024-03-26