Flutter for windows实现思维导图架构图

248 阅读1分钟

使用的插件

graphview: ^1.2.0

效果图

image.png

优点

1.item可以自定义;
2.当前页面无法全部展示时,可以进行拖拽查看;
3.可以鼠标滚轮进行放大缩小

缺点

1.节点不能多对多进行链接;

主要代码

代码中使用了自己的状态管理框架,可以直接去掉,使用stateflu 即可

import 'package:flutter/material.dart';
import 'package:graphview/GraphView.dart';
import 'package:ui_state/state_widget.dart';
import 'logic.dart';
import '../../../system/kit.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("班级组织架构"),
      ),
      body: StateWidget(
        logic: TreeLogic(context),
        builder: (logic) => InteractiveViewer(
          constrained: false,
          boundaryMargin: const EdgeInsets.all(50),
          minScale: 0.01,
          maxScale: 5.6,
          // alignment: Alignment.bottomLeft,
          child: GraphView(
            graph: logic.graph,
            algorithm: BuchheimWalkerAlgorithm(
                logic.builder1, TreeEdgeRenderer(logic.builder1)),
            paint: Paint()
              ..color = Colors.green
              ..strokeWidth = 1
              ..style = PaintingStyle.stroke,
            builder: (Node node) {
              var a = node.key!.value as int?;
              var nodes = logic.json['nodes']!;
              var nodeValue = nodes.firstWhere((element) => element['id'] == a);
              return rectangleWidget(nodeValue["label"] as Map);
            },
          ),
        ),
      ),
    );
  }
}

Widget rectangleWidget(Map nodes) {
  List<Map<String, String>> list = nodes["list"];
  return InkWell(
    onTap: () {},
    child: Container(
      padding: nodes["tag"] == "h"
          ? const EdgeInsets.fromLTRB(0, 5, 0, 5)
          : const EdgeInsets.all(5),
      decoration: BoxDecoration(
        border: Border.all(width: 1, color: Colors.grey.shade500),
        color: Colors.white,
      ),
      child: nodes["tag"] == "h"
          ? Row(
              children: list
                  .map(
                    (e) => Padding(
                      padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
                      child: Container(
                        decoration: BoxDecoration(
                          boxShadow: [
                            BoxShadow(
                                color: Colors.blue.shade100, spreadRadius: 1),
                          ],
                        ),
                        child: Padding(
                          padding: const EdgeInsets.all(5),
                          child: Row(
                            children: [
                              kit.avatar(imageUrl: "${e["image"]}", size: 30),
                              Padding(
                                padding: const EdgeInsets.only(left: 5),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text("${e["name"]}"),
                                    Text("${e["job"]}",style: TextStyle(color: Colors.grey.shade500,fontSize: 14),),
                                  ],
                                ),
                              )
                            ],
                          ),
                        ),
                      ),
                    ),
                  )
                  .toList(),
            )
          : Column(
              children: [
                Text("${nodes["group"]}"),
                Column(
                  children: list
                      .map(
                        (e) => Padding(
                          padding: const EdgeInsets.only(bottom: 10),
                          child: Container(
                            width: 150,
                            // height: 60,
                            decoration: BoxDecoration(
                              boxShadow: [
                                BoxShadow(
                                    color: Colors.blue.shade100,
                                    spreadRadius: 1),
                              ],
                            ),
                            child: ListTile(
                              contentPadding:
                                  const EdgeInsets.fromLTRB(5, 0, 0, 5),
                              leading: kit.avatar(
                                  imageUrl: "${e["image"]}", size: 30),
                              // titleAlignment: ListTileTitleAlignment.center,
                              title: Text(
                                "${e["name"]}",
                              ),
                              subtitle: e.containsKey("job")
                                  ? Text(
                                      "${e["job"]}",
                                      overflow: TextOverflow.ellipsis,
                                    )
                                  : const SizedBox.shrink(),
                            ),
                          ),
                        ),
                      )
                      .toList(),
                )
              ],
            ),
    ),
  );
}