gojs在vue中实现画布流程

GoJS 是一个用于实现交互式图表的 JavaScript 库,详情可查看官网

根据官网samples实现以下demo
在这里插入图片描述

1.安装gojs插件

npm install gojs --save
或者yarn add gojs

2.在vue组件中引入

import go from "gojs";
const $ = go.GraphObject.make;
const palettes={
     palette0: [
        { palette: "0", type: "start", text: "开始", nyColor: null, from: true },
        { palette: "0", type: "stop", text: "结束", nyColor: null, to: true },
        {
            palette: "0",
            type: "type1",
            text: "demo1",
            label: "双击设置",
            nyColor: null,
            from: true,
            to: true,
        },
        {
            palette: "0",
            type: "type2",
            text: "demo2",
            label: "双击设置",
            nyColor: null,
            from: true,
            to: true,
        },
    ],
    palette1: [
        {
            palette: "1",
            type: "type3",
            text: "demo3",
            label: "双击设置",
            nyColor: null,
            from: true,
            to: true,
        },
          {
            palette: "1",
            type: "type4",
            text: "demo4",
            label: "双击设置",
            nyColor: null,
            from: true,
            to: true,
          },
        {
            palette: "1",
            type: "type5",
            text: "demo5",
            label: "双击设置",
            nyColor: null,
            from: true,
            to: true,
        },   
    ],
}
let diagram = null;

3.创建div标签元素

<div class="content">
   <div class="left">
      <div id="palette0" class="palette"></div>
      <div id="palette1" class="palette"></div>
   </div>
   <div class="right">
      <div id="diagram" :style="{ height:  'calc(100vh - 305px)' }"></div>
   </div>
</div>

样式部分

.content{
   display:flex;
   .left{
      width:300px;
      .palette {
        width: 100%;
        height: 150px;
      }
   }
   .right{
      flex:1
   }
}

4.行为部分(script)

data() {
    return {
      nodesData: {},
      isReadOnly: false,
    };
},
mounted() {
    that = this;
    diagram = this.createDiagram();
    //   diagram.model = go.Model.fromJson({});
    diagram.commandHandler.canDeleteSelection = function (e) {
      //用例获取选中的节点或线
      return diagram.selection.all(function (nodeOrLink) {
        // console.log(nodeOrLink.data);
        //判断是否存在不允许删除的节点或线
        if (nodeOrLink.data.text == "结束" || nodeOrLink.data.text == "开始") {
          return false;
        } else {
          return true;
        }
      });
    };
    diagram.model.linkFromPortIdProperty = "fromPort";
    diagram.model.linkToPortIdProperty = "toPort";
      diagram.model.nodeDataArray = [
        {
          palette: "0",
          key: -1,
          type: "start",
          text: "开始",
          from: true,
          img: require("@/assets/icons/icons8-start.png"),
        },
        {
          palette: "0",
          key: -3,
          type: "stop",
          text: "结束",
          to: true,
          img: require("@/assets/icons/icons8-stop.png"),
        },
      ];
    this.createPalette("palette0", palettes.palette0);
    this.createPalette("palette1", palettes.palette1);
    //this.init();用于回显画布内容
  },
  beforeDestroy() {
    diagram.model = go.Model.fromJson({});
  },
  methods:{
    init(){
          const configs = JSON.parse({});
          configs["nodes"].forEach((node) => {
            that.nodesData[node["current"]] = node["config"];
          });
          configs["diagram"]["nodeDataArray"].forEach((nodeData) => {
            nodeData["img"] = require("@/assets/icons/icons8-task-160.png");
          });
          configs["diagram"]["linkFromPortIdProperty"] = "fromPort";
          configs["diagram"]["linkToPortIdProperty"] = "toPort";
          diagram.model = go.Model.fromJson(configs["diagram"]);
    },
    createDiagram() {
      return $(go.Diagram, "diagram", {
        grid: $(
          go.Panel,
          "Grid",
          $(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5 }),
          $(go.Shape, "LineH", {
            stroke: "gray",
            strokeWidth: 0.5,
            interval: 10,
          }),
          $(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5 }),
          $(go.Shape, "LineV", {
            stroke: "gray",
            strokeWidth: 0.5,
            interval: 10,
          })
        ),
        validCycle: go.Diagram.CycleNotDirected,
        "undoManager.isEnabled": true,
        nodeTemplate: this.getNodeTemplate(),
        linkTemplate: $(
          go.Link,
          { selectable: true },
          {
            routing: go.Link.AvoidsNodes,
            corner: 5,
            toShortLength: 4,
          },
          new go.Binding("points").makeTwoWay(),
          $(go.Shape, { isPanelMain: true, strokeWidth: 2 }),
          $(go.Shape, { toArrow: "Standard", stroke: null })
        ),
        ExternalObjectsDropped: (e) => {
          e.subject.each((part) => {
            let type = part.data.type;
            if (type === "start") {
              if (diagram.model.findNodeDataForKey(-1)) {
                that.$message.error("节点已存在");
                diagram.remove(part);
              }
            } else if (type === "stop") {
              if (diagram.model.findNodeDataForKey(-3)) {
                that.$message.error("节点已存在");
                diagram.remove(part);
              }
            }
          });
        },
      });
    },
    createPalette(id, models) {
      models.forEach((model) => {
        model["img"] = require("@/assets/icons/icons8-task-160.png");
      });
      $(go.Palette, id, {
        nodeTemplate: $(
          go.Node,
          go.Panel.Horizontal,
          { desiredSize: new go.Size(100, 20), margin: 0 },
          $(
            go.Picture,
            { maxSize: new go.Size(16, 16) },
            new go.Binding("source", "img")
          ),
          $(
            go.TextBlock,
            { maxSize: new go.Size(100, NaN) },
            new go.Binding("text", "text")
          ),
          {
            selectionAdornmentTemplate: $(
              go.Adornment,
              "Auto",
              $(go.Shape, { fill: null, strokeWidth: 0 }),
              $(go.Placeholder)
            ),
          }
        ),
        model: new go.GraphLinksModel(models),
      });
    },
    getNodeTemplate() {
      return $(
        go.Node,
        "Spot",
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
          go.Point.stringify
        ),
        $(
          go.Panel,
          "Auto",
          $(
            go.Shape,
            "RoundedRectangle",
            {
              portId: null,
              fromLinkableDuplicates: false,
              toLinkableDuplicates: false,
              fromLinkableSelfNode: false,
              toLinkableSelfNode: false,
              cursor: "pointer",
              fill: "white",
              stroke: "#DCDFE6",
              strokeWidth: 1,
            },
            new go.Binding("fromLinkable", "from"),
            new go.Binding("toLinkable", "to")
          ),
          $(
            go.Panel,
            "Horizontal",
            $(
              go.Picture,
              { maxSize: new go.Size(40, 40) },
              new go.Binding("source", "img")
            ),
            $(
              go.Panel,
              "Vertical",
              { defaultAlignment: go.Spot.Left, margin: 5 },
              $(
                go.TextBlock,
                { font: "bold 12px sans-serif" },
                new go.Binding("text", "text")
              ),
              $(
                go.TextBlock,
                {
                  maxSize: new go.Size(100, NaN),
                  wrap: "WrapFit",
                  font: "normal 11px sans-serif",
                  stroke: "#909399",
                },
                new go.Binding("text", "label")
              )
            )
          )
        ),
        this.makePort("T", go.Spot.Top, false, true),
        this.makePort("B", go.Spot.Bottom, true, false),
        this.makePort("BL", go.Spot.BottomLeft, true, false),
        this.makePort("BR", go.Spot.BottomRight, true, false),
        {
          selectionAdornmentTemplate: $(
            go.Adornment,
            "Auto",
            $(go.Shape, "RoundedRectangle", {
              fill: null,
              stroke: "#303133",
              strokeWidth: 1,
            }),
            $(go.Placeholder)
          ), // 设置选中效果
          linkValidation: that.linkValidation,
          mouseEnter: (e, node) => {
            node.ports.each((port) => {
              if (port.portId === "T") {
                port.fill = node.data.to ? "#16BEFF" : null;
              } else if (port.portId === "B" && node.data.type != "decision") {
                port.fill = node.data.from ? "#16BEFF" : null;
              } else if (
                port.portId === "BL" &&
                node.data.type === "decision"
              ) {
                port.fill = node.data.from ? "#16BEFF" : null;
              } else if (
                port.portId === "BR" &&
                node.data.type === "decision"
              ) {
                port.fill = node.data.from ? "#16BEFF" : null;
              }
            });
          },
          mouseLeave: (e, node) => {
            node.ports.each((port) => {
              if (
                port.portId === "T" ||
                port.portId === "B" ||
                port.portId === "BL" ||
                port.portId === "BR"
              ) {
                port.fill = null;
              }
            });
          },
          doubleClick: (e, node) => {
            const type = node.data.type;
            let key = type + node.data.key;
            console.log(type,key)
          },
        }
      );
    },
     makePort(name, spot, output, input) {
      return $(
        go.Panel,
        "Horizontal",
        { alignment: spot, alignmentFocus: spot },
        $(
          go.TextBlock,
          //   { font: "500 12px sans-serif", text: name == "BL" ? Y : null },
          { font: "500 12px sans-serif", text: name == "BL" ? null : null },
          new go.Binding("stroke", "nyColor")
        ),
        $(go.Shape, "Circle", {
          fill: null,
          stroke: null,
          desiredSize: new go.Size(7, 7),
          portId: name,
          fromSpot: spot,
          toSpot: spot,
          fromLinkable: output,
          toLinkable: input,
          cursor: "pointer",
          fromMaxLinks: name == "BR" || name == "BL" ? 1 : 5,
        }),
        $(
          go.TextBlock,
          //   { font: "500 12px sans-serif", text: name == "BR" ? N : null },
          { font: "500 12px sans-serif", text: name == "BR" ? null : null },
          new go.Binding("stroke", "nyColor")
        )
      );
    },
    // 校验节点间是否可连接通过返回true或者false允许和静止连接
    linkValidation(fromNode, fromPort, toNode, toPort) {
      const fromPalette = fromNode.data.palette;
      const fromType = fromNode.data.type;
      const toPalette = toNode.data.palette;
      const toType = toNode.data.type;
            let isRight = false; // 连线是否正确
      let linkedOtherCount = 0; // 已经连接了几个节点
      let beLinkedCount = 0; // 已经被几个节点连接
      fromNode.findNodesOutOf().each(() => {
        linkedOtherCount++;
      });
      toNode.findNodesInto().each(() => {
        beLinkedCount++;
      });
      console.log(
        "from",
        fromType,
        "to",
        toType,
        "连几个",
        linkedOtherCount,
        "被几个",
        beLinkedCount,
        "parent",
        fromPalette,
        "parent",
        toPalette,
        "fromPort",
        fromPort,
        "toPort",
        toPort
      );
      return true;
    }
  }

获取diagram生成的json数据

diagram.model.modelData.position =
go.Point.stringify(diagram.position); let model =
JSON.parse(diagram.model.toJson()); console.log(“diagram”, model);

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue实现工艺流程图可以使用一些第三方库来辅助实现,其比较常用的是`vue-dagre`和`vue-graph`。 1. `vue-dagre`: 这是一个基于Dagre库的Vue组件,可以用于绘制有向无环图(DAG)。你可以通过安装和引入该库来使用它。首先,在终端运行以下命令来安装该库: ``` npm install vue-dagre ``` 然后,在你的Vue组件引入该库: ```javascript import VueDagre from 'vue-dagre' export default { components: { VueDagre }, // ... } ``` 接下来,你可以在模板使用`vue-dagre`组件来绘制工艺流程图。例如: ```html <template> <div> <vue-dagre :nodes="nodes" :edges="edges"></vue-dagre> </div> </template> <script> export default { data() { return { nodes: [ { id: 'A', label: 'Step A' }, { id: 'B', label: 'Step B' }, // ... ], edges: [ { id: 'AB', source: 'A', target: 'B' }, // ... ] } }, // ... } </script> ``` 2. `vue-graph`: 这是一个用于绘制图形和关系图的Vue组件库,支持自定义节点和边的样式。你可以通过安装和引入该库来使用它。首先,在终端运行以下命令来安装该库: ``` npm install vue-graph ``` 然后,在你的Vue组件引入该库: ```javascript import VueGraph from 'vue-graph' export default { components: { VueGraph }, // ... } ``` 接下来,你可以在模板使用`vue-graph`组件来绘制工艺流程图。例如: ```html <template> <div> <vue-graph :nodes="nodes" :edges="edges"></vue-graph> </div> </template> <script> export default { data() { return { nodes: [ { id: 'A', label: 'Step A' }, { id: 'B', label: 'Step B' }, // ... ], edges: [ { id: 'AB', source: 'A', target: 'B' }, // ... ] } }, // ... } </script> ``` 以上是两个常用的Vue库,可以帮助你实现工艺流程图。根据你的具体需求和图表样式,你可以选择其一个或者根据自己的需求进行定制化开发。希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值