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();
算法总览
先从叶子往上测量,后从根节点往下布局
测量
从父节点开始一直迭代到叶子节点,让子节点都向父节点返回测量结果。
如果子节点是叶子节点,把节点的大小计算即可,
如果子节点还有子节点,那么让子节点计算其自己的大小
节点子节点有子节点时: 获取每个子节点的大小(是一个矩形区域),把多个子节点的矩形区域区域,环绕节点一圈,然后计算节点 + 环绕的子节点区域,组成的矩形区域,返回给父节点计算
以上是测量步骤的迭代过程,因为用了矩形区域来限定子节点的位置,所以节点永不重叠
测量结果包括:
- 每一级中,节点和子节点的距离
- 每一级中,子节点的的角度
- 每一级中,基于当前节点为(0, 0),节点和子节点所占的区域
布局
给定一个根节点开始布局的位置,按之前测量的结果,往下布局
渲染和计算讨论
位置计算
可预料到这种算法在大量的数据下,会非常耗费性能,需要优化
情况分析:
- 算法的输入是节点结构,输出是节点的坐标,输入输出数据量不大。结论:不需要把性能耗费在序列化上,所以可很效率地使用dart isolate
- 节点的计算不需要实时性,用户扩展节点后,可等待一段时间再看到节点展开。结论:可以让dart isolate在背后计算,然后主isolate优先处理界面显示,显示优先
创建一个专门计算节点位置的isolate,它不停输出节点的位置,界面根据这些位置进行显示,甚至做动画效果
大量节点的渲染
利用缓存
如果节点图形很复杂,我们可以利用缓存
利用缩放特性
遵循以下规则
- 当节点在屏幕外部,不渲染(如果有算法可以输入region迅速找到对应节点更好,如google s2算法)
- 不能无限制缩小节点图
然后根据三种缩放倍率,节点会有显示方式和效果的不同
能力/倍率 | 小 | 中 | 大 |
---|---|---|---|
绘制模式 | canvas | canvas | Widget |
可否动画 | 否,一次渲染成图片 | 可 | 可 |
样式 | 单一几何形状 | 复杂形状 | 可任意复杂组件 |
是否随机浮动 | 否 | 是 | 是 |
节点扩展动画 | 否 | 否 | 否 |
是否可交互 | 否 | 否 | 是 |
由于我们现在能精确计算节点的位置,所以对于canvas和Widget的绘制形式可用动画做到无缝切换
开发计划
- 设计布局算法,相同的节点结构输入,就有相同的位置输出,且不重叠,
- 目前优化对于空间利用不高,需要优化
- 把用子节点矩形中高最大的矩形计算节点到子节点距离改为*用每一个矩形高,在分配的角度下,计算半径
- 计算节点和子节点的矩形区域盒子时,应当计算子节点矩形区域内的节点,而不是只计算矩形区域
- 在单独的isolate计算节点位置
- isolate在接收到节点结构后,计算节点位置信息,向主isolate刷新节点位置信息
- isolate接收主isolate发送的命令,如展开节点等,isolate向主isolate刷新节点位置信息
- 封装Widget组件显示节点位置,绘制连线
- 不同倍率下不同的节点绘制方式
- 绘制方式
- Canvas绘制节点
- Widget显示节点
- 随机移动
- 节点扩展动画
- 绘制方式