g6图形化开发 - vue项目(结尾处附代码)

G6参考文档[https://g6.antv.vision/zh](https://g6.antv.vision/zh)

官方简介:G6是一个简单、易用、完备的图可视化引擎,它在高定制能力的基础上,提供了一系列设计优雅、便于使用的图可视化解决方案。能帮助开发者搭建属于自己的图可视化、图分析、或图编辑器应用。

初始化—>加载数据—>渲染—>更新—>销毁
G6.Graph、data(data)、render()、changeData(data)、clear()

初始化

  1. 页面mounted的,初始化G6实例,以及默认点、边属性
  2. 注册自定义边样式
  3. menu自定义

加载数据

graph.data(this.data)

渲染

graph.render()

更新

  1. 新增点
graph.addItem("node", {
     label: e.name,
     resource_id: e.resourceId,
     resource_type: e.resourceType,
     code: e.code,
     x: e.x + 150 * (i + 1),
     y: e.y + 100 * (i + 1),
     img: imageName,
})

  边的新增,可以在初始化G6的时候,在models的defaults中加入"create-edge"
2. 删除点、边

graph.removeItem(_cfg.id)

3. G6布局样式调整

graph.updateLayout({
     type: "grid",
     begin: [0, 0], // 可选,
     preventOverlap: true, // 可选,必须配合 nodeSize
     preventOverlapPadding: 40, // 可选
     nodeSize: 60, // 可选
     condense: false, // 可选
     rows: 5, // 可选
     cols: 5, // 可选
     sortBy: "degree", // 可选
     workerEnabled: true,
})    

销毁

graph.clear()

 

  • 附上项目部分代码
<template>
    <div id="topo-container">
      <div id="mountNode"></div>
      <!-- 新增连线弹窗 -->
      <el-dialog
        title="关系选择"
        :visible.sync="relationVisible"
        width="350px">
        <el-select v-model="relate" placeholder="请选择" value-key="id">
          <el-option
            v-for="item in relations"
            :key="item.id"
            :label="item.name"
            :value="item">
          </el-option>
        </el-select>
        <span slot="footer" class="dialog-footer">
          <el-button @click="relationVisible = false">取 消</el-button>
          <el-button type="primary" @click="handleSaveRelation">确 定</el-button>
        </span>
      </el-dialog>
    </div>
  </template>
  
  <script>
  import G6 from "@antv/g6";
  import { getTopoValue, getMdRelation } from "@/api/resource/topology";
  let graph = null;
  // 初始化—>加载数据—>渲染—>更新—>销毁
  // G6.Graph、data(data)、render()、changeData(data)、clear()
  
  export default {
    name: "topoContent",
    props: ['defaultEdge', 'lineAllObj', 'currentId'],
    data() {
      return {
        data: {
          nodes: [],
          edges: [],
        },
        lineList: [],  // 边类型 4类
        relationVisible: false,  // 关系选择弹窗
        relations: [],
        relate: '',  // 选中的关系
        editEdge: {},  // 当前正在编辑的边
      };
    },
    watch: {
      defaultEdge: {
        deep: true,  // 深度监听
        handler(newVal,oldVal) {
          graph.cfg.defaultEdge.style = newVal.defaultEdgeStyle;
          graph.cfg.defaultEdge.edgeType = newVal.edgeType;
        }
      },
      currentId: {
        deep: true,  // 深度监听
        handler(newVal,oldVal) {
          this.getTopoValue (newVal)
        }
      },
    },
    mounted() {
      let container = document.getElementById("mountNode");
      const width = container.scrollWidth;
      const height = container.scrollHeight || 500;
  
      G6.registerEdge(
        "line-arrow",
        {
          getPath(points) {
            const startPoint = points[0];
            const endPoint = points[1];
            return [
              ["M", startPoint.x, startPoint.y],
              ["L", endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],
              ["L", endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],
              ["L", endPoint.x, endPoint.y],
            ];
          },
          getShapeStyle(cfg) {
            const startPoint = cfg.startPoint;
            const endPoint = cfg.endPoint;
            const controlPoints = this.getControlPoints(cfg);
            let points = [startPoint]; 
            if (controlPoints) {
              points = points.concat(controlPoints);
            }
            points.push(endPoint);
            const path = this.getPath(points);
            const style = Object.assign(
              {},
              G6.Global.defaultEdge.style,
              {
                stroke: "#BBB",
                lineWidth: 1,
                path,
              },
              cfg.style
            );
            return style;
          },
        },
        "line"
      );
  
      let _this = this
      const contextMenu = new G6.Menu({
        getContent(evt) {
          let item = evt.item._cfg
          if (item.type == 'edge'){
            let source_resource_type = item.sourceNode._cfg.model.resource_type || ''
            let target_resource_type = item.targetNode._cfg.model.resource_type || ''
            if (source_resource_type == '' || target_resource_type == '') {  // 线上的点存在是拓扑树节点 此时没有关系选择
              return `
              <ul>
                  <li code='remove'>删除</li>
              </ul>`;
            } else {
              _this.editEdge = {
                resourceId: item.model.source,
                resourceTypeId: source_resource_type,
                targetId: item.model.target,
                targetTypeId: target_resource_type
              }
              return `
              <ul>
                  <li code='choose'>选择关系</li>
                  <li code='remove'>删除</li>
              </ul>`;
            }
          } else {
            return `
            <ul>
                <li code='edit'>编辑</li>
                <li code='remove'>删除</li>
            </ul>`;
          }
        },
        handleMenuClick: (target, item) => {
          let code = target.attributes.code? target.attributes.code.value : '';
          if (code === "edit") {
            this.$emit("isShowEdit", item, false);
          } else if (code === "remove") {
            graph.removeItem(item._cfg.id);
          } else if (code === "choose") {
            this.loadRelationList()
          }
        },
        offsetX: -250,
        offsetY: -120,
        itemTypes: ["node", "edge"],
      });
      graph = new G6.Graph({
        container: "mountNode",
        width,
        height,
        plugins: [contextMenu],
        // fitView:true,
        // fitViewPadding: 40,
        // layout: {
        //     type: 'dagre',
        //     rankdir: 'LR', // 可选,默认为图的中心
        //     align: 'DL', // 可选
        //     nodesep: 20, // 可选
        //     ranksep: 50, // 可选
        //     controlPoints: true, // 可选
        // },
        defaultNode: {
          type: "image",
          size: [40, 40],
          img: '/3.png',
          style: {
            radius: 5,
            stroke: "#69c0ff",
            fill: "#ffffff",
            lineWidth: 1,
            fillOpacity: 1,
          },
          labelCfg: {
            style: {
              fill: "#595959",
              fontSize: 12,
            },
            // offset: 20,
          },
        },
        defaultEdge: {
          type: "line-arrow",
          style: {
            stroke: "#0099CC",
            // startArrow: {
            //     path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
            //     fill: '#0099CC',
            // },
            endArrow: {
              path: "M 0,0 L 12,6 L 9,0 L 12,-6 Z",
              fill: "#0099CC",
            },
            lineDash: [],
          },
          // style: {
          //     stroke: '#b5b5b5',
          //     lineAppendWidth: 2,
          //     endArrow: true,
          //     lineDash: []
          // },
          // labelCfg: {
          //     autoRotate: true,
          //     style: {
          //         stroke: 'white',
          //         lineWidth: 1,
          //     },
          // },
        },
        modes: {
          default: ["drag-canvas", "zoom-canvas", "drag-node", "create-edge"],
        },
      });
      this.getTopoValue (this.currentId)
    },
    methods: {
      // 查询拓扑图数据
      getTopoValue (id) {
        getTopoValue(id)
          .then((res) => {
            let { nodes, edges } = res.data.data;
            nodes = this.initNodeData(nodes);
            edges = this.initEdgeData(edges);
            this.data = { nodes, edges };
            this.loadGraph()
          })
          .catch((err) => {
            console.log("获取拓扑数据失败", err);
          });
      },
      initNodeData(nodes) {
        nodes.forEach((o) => {
          o.id = o.id.toString();
          o.label = o.label.toString();
        });
        return nodes;
      },
  
      initEdgeData(edges) {
        edges.forEach((o) => {
          o.source = o.source.toString();
          o.target = o.target.toString();
          o.edgeType = o.edge_type;
          o.style = this.lineAllObj[o.edge_type];
  
        });
        return edges;
      },
      // 加载拓扑图
      loadGraph() {
        let container = document.getElementById("mountNode");
  
        graph.data(this.data);
        graph.render();
        this.$emit("graphGet", graph);
  
        graph.on("aftercreateedge", (e) => {
          const edges = graph.save().edges;
          console.log(edges, "edges");
          G6.Util.processParallelEdges(edges);
          graph.getEdges().forEach((edge, i) => {
            graph.updateItem(edge, {
              curveOffset: edges[i].curveOffset,
              curvePosition: edges[i].curvePosition,
            });
          });
        });
  
        if (typeof window !== "undefined")
          window.onresize = () => {
            if (!graph || graph.get("destroyed")) return;
            if (!container || !container.scrollWidth || !container.scrollHeight)
              return;
            graph.changeSize(container.scrollWidth, container.scrollHeight);
          };
      },
      // 加载关系list
      loadRelationList () {
        getMdRelation(this.editEdge).then(res => {
          this.relationVisible = true
          this.relations = res.data.data || []
        }).catch(err => {
          console.log('查询报错',err)
        })
      },
      // 关系选择确认
      handleSaveRelation () {
        // 更改线的数据
        // 通过 ID 查询节点实例
        const item = graph.findById(this.editEdge.id);
        graph.updateItem(item, {...this.editEdge, label: this.relate.name, relationType: this.relate.relationType});
        this.relationVisible = false
      },
      handlerLayout() {
        graph.updateLayout({
          type: "grid",
          begin: [0, 0], // 可选,
          preventOverlap: true, // 可选,必须配合 nodeSize
          preventOverlapPadding: 40, // 可选
          nodeSize: 60, // 可选
          condense: false, // 可选
          rows: 5, // 可选
          cols: 5, // 可选
          sortBy: "degree", // 可选
          workerEnabled: true,
        });
      },
      handlerSave() {
        let edgesAll = graph.getEdges(),
          nodesAll = graph.getNodes();
        let data = { edges: [], nodes: [] };
        edgesAll.forEach((item) => {
          data.edges.push(item._cfg.model);
        });
        nodesAll.forEach((item) => {
          data.nodes.push(item._cfg.model);
        });
        console.log("保存的数据data:", data);
      },
    },
  };
  </script>
  
  <style lang="scss">
  #topo-container {
    #mountNode {
      position: relative;
      overflow: hidden;
      ul {
        list-style-type: none;
        left: -150px;
        margin: 0;
        padding: 10px;
        background-color: rgba(255, 255, 255, 0.9);
        border-radius: 4px;
        font-size: 12px;
        color: #545454;
        li {
          cursor: pointer;
          list-style-type: none;
          list-style: none;
          margin-left: 0px;
          margin-bottom: 5px;
          &:hover {
            color: #aaa;
          }
        }
      }
    }
  }
</style>


 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值