关于GoJs的总结及多功能实例

项目需要用到GoJs实现可视化,先说一下需求吧

1、实现可拖拽新建节点

2、点击节点可修改保存节点信息

3、可以手动新建节点之间的连线

4、点击连线可修改保存连线信息

5、节点鼠标右键菜单

网上的都是零零碎碎的,查了很多文档然后终于实现了上述的所有功能...

废话不多说,直接上代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>dsDemo</title>
  <meta name="description" content="A workflow diagram showing navigation between web pages, with an editable list of comments and to-dos." />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
</head>
<body>
<div id="container">
   <div style="width: 100%; display: flex; justify-content: space-between">
      <div id="myPaletteDiv" style="width: 150px; margin-right: 2px; background-color: whitesmoke; border: solid 1px black"></div>
      <div id="myDiagramDiv" style="flex-grow: 1; height: 600px; border: solid 1px black"></div>
      <div id="nodeDetail"  style="width:200px; margin-right: 2px; background-color: whitesmoke; border: solid 1px black;padding:10px">
        <p style="text-align: left">节点名称:<input type="text" v-model="selectNode.name"/></p>
        <p style="text-align: left">节点描述:</p>
        <textarea v-model="selectNode.description" style="width:98%;height:200px"></textarea>
        <button id="SaveButton" @click="saveNode">保存</button>
      </div>
      <div id="linkDetail" style="width:200px; margin-right: 2px; background-color: whitesmoke; border: solid 1px black;padding:10px;display:none;">
        <p style="text-align: left">连线名称:<input type="text" v-model="selectLink.name"/></p>
        <p style="text-align: left">连线描述:</p>
        <textarea v-model="selectLink.description" style="width:98%;height:200px"></textarea>
        <button id="SaveButton" @click="saveLink">保存</button>
      </div>
    </div>
</div>
</body>
 <script src="./go.js"></script>
  <script src="./vue.min.js"></script>
  <script id="code">
   new Vue({
        el:'#container',
        data:{
            selectNode:{
                name:'',
                description:''
            },
            selectLink:{
                name:'',
                description:''
            }
        },
        methods:{
            saveNode(){   //保存节点信息
              this.myDiagram.model.updateTargetBindings(this.selectNode);
            },
            saveLink(){
              this.myDiagram.model.updateTargetBindings(this.selectLink);
            }
        },
        mounted(){
            var mySelf = this;
            const MAKE = go.GraphObject.make;
            mySelf.myDiagram  = MAKE(go.Diagram, "myDiagramDiv",{
                "draggingTool.dragsLink": true,
                "undoManager.isEnabled": true ,// 支持 Ctrl-Z 和 Ctrl-Y 操作
                "toolManager.hoverDelay": 100,//tooltip提示显示延时
                "toolManager.toolTipDuration": 10000,//tooltip持续显示时间
                //isReadOnly:true,//只读
                // "grid.visible":true,//显示网格
                allowMove:true,//允许拖动
                // allowDragOut:true,
                allowDelete:false,
                allowCopy:false,
                allowClipboard:false,
                "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,//有鼠标滚轮事件放大和缩小,而不是向上和向下滚动
            });
            
            var that=this;
            mySelf.myDiagram.addDiagramListener("ObjectSingleClicked",function (e) {
                if(e.subject.part.data.key == undefined){
                    that.selectLink=e.subject.part.data;
                    document.getElementById("nodeDetail").style.display="none";
                    document.getElementById("linkDetail").style.display="block";
                }else{
                    that.selectNode=e.subject.part.data;
                    document.getElementById("nodeDetail").style.display="block";
                    document.getElementById("linkDetail").style.display="none";
                }
            });
            mySelf.myDiagram.addModelChangedListener(function (evt) {
              if (!evt.isTransactionFinished) return;
              var txn = evt.object;
              if (txn === null) return;
              txn.changes.each(function(e) {
                if (e.modelChange !== "nodeDataArray") return;
                if (e.change === go.ChangedEvent.Insert) {
                  that.selectNode=e.newValue;
                }
              });
            });
            

            // 定义个简单的 Node 模板
            mySelf.myDiagram.nodeTemplate =
              MAKE(go.Node, "Auto",
                new go.Binding("location", "loc", go.Point.parse),
                MAKE(go.Shape, "RoundedRectangle",
                  {
                    fill: "#fff",stroke: '#289de9',strokeWidth:1
                  }),
                MAKE(go.TextBlock, "new node",
                  {
                    margin: 8 ,
                    font: "bold 14px Helvetica Neue",
                  },
                  new go.Binding("text", "name")));
                  
            function makePort(name, align, spot, output, input) {
                var horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
                return MAKE(go.Shape,
                  {
                    fill: "transparent",  // changed to a color in the mouseEnter event handler
                    strokeWidth: 0,  // no stroke
                    width: horizontal ? NaN : 8,  // if not stretching horizontally, just 8 wide
                    height: !horizontal ? NaN : 8,  // if not stretching vertically, just 8 tall
                    alignment: align,  // align the port on the main Shape
                    stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),
                    portId: name,  // declare this object to be a "port"
                    fromSpot: spot,  // declare where links may connect at this port
                    fromLinkable: output,  // declare whether the user may draw links from here
                    toSpot: spot,  // declare where links may connect at this port
                    toLinkable: input,  // declare whether the user may draw links to here
                    cursor: "pointer",  // show a different cursor to indicate potential link point
                    mouseEnter: function(e, port) {  // the PORT argument will be this Shape
                      if (!e.diagram.isReadOnly) port.fill = "rgba(255,0,255,0.5)";
                    },
                    mouseLeave: function(e, port) {
                      port.fill = "transparent";
                    }
                  });
            }
        
            function textStyle() {
                return {
                  font: "bold 11pt Helvetica, Arial, sans-serif",
                  stroke: "whitesmoke"
                }
            }
            mySelf.myDiagram.nodeTemplateMap.add("",  // the default category
                MAKE(go.Node, "Auto",
                 {
                    contextMenu:     // define a context menu for each node
                      MAKE("ContextMenu",  // that has one button
                        MAKE("ContextMenuButton",
                          MAKE(go.TextBlock, "Undo"),
                            {
                                click: function(e, obj) {
                                     console.log(1)
                                }
                            },
                      ))  
                  },
                  MAKE(go.Panel, "Auto",
                    MAKE(go.Shape, "RoundedRectangle",
                       {
                    fill: "#fff",stroke: '#289de9',strokeWidth:1
                  }),
                    MAKE(go.TextBlock, "new node",
                      {
                        margin: 8,
                        font: "bold 14px Helvetica Neue",
                      },
                      new go.Binding("text","name").makeTwoWay())
                  ),
                  // four named ports, one on each side:
                  makePort("T", go.Spot.Top, go.Spot.TopSide, false, true),
                  makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
                  makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
                  makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, false)
                ));      
                  
                  
            //定义连线
            var linkSelectionAdornmentTemplate =
            MAKE(go.Adornment, "Link",
              MAKE(go.Shape,
                // isPanelMain declares that this Shape shares the Link.geometry
                { isPanelMain: true, fill: null, stroke: "deepskyblue", strokeWidth: 0 })  // use selection object's strokeWidth
            );
            mySelf.myDiagram.linkTemplate =
                MAKE("Link",
                  MAKE("Shape",
                    { strokeWidth: 2,stroke: '#289de9'}),
                  MAKE("Shape",
                    { toArrow: "Standard", fill:"#289de9",stroke:null}),
                  MAKE(go.TextBlock, "new link",
                    {
                      margin: 8,
                      font: "bold 14px Helvetica Neue",
                      segmentOffset: new go.Point(0, -10)
                    },
                    new go.Binding("text","name").makeTwoWay()),
                );

            var palette =
              MAKE(go.Palette, "myPaletteDiv",  // create a new Palette in the HTML DIV element
                {
                  // share the template map with the Palette
                  nodeTemplateMap: mySelf.myDiagram.nodeTemplateMap,
                  autoScale: go.Diagram.Uniform  // everything always fits in viewport
                });
            palette.model.nodeDataArray = [
              {}, // default node
            ];

            let myModel = MAKE(go.GraphLinksModel);
            myModel.nodeDataArray =
              [
               // {key:"1", name: "a",age:12,description:'我是a节点'},
                //{key:"2", parent:"1", name: "b",age:13 ,description:'我是b节点'},
                //{key:"3", parent:"1", name: "c",age:13 ,description:'我是b节点'},
              ];
            myModel.linkDataArray = [
               //{from:"1",to:"2"},
               //{from:"1",to:"3"},
        //       {from:"1",to:"4"},
        //       {from:"1",to:"5"},
           ];
            mySelf.myDiagram.model = myModel;
        }
    })
  </script>
</html>

 

关于GoJs的方法

(Ps:这里只写我觉得比较常用的,其他的请自行查阅其他文档,谢谢!)

1.更新数据

this.myDiagram.model.updateTargetBindings(this.selectNode);

参数是你当前编辑的数据,这里可以是节点信息也可以是连线信息

2.mySelf.myDiagram.addDiagramListener("ObjectSingleClicked",function (e) {
                   console.log(e.subject.part.data);
   });

监听点击事件,可以是点击节点也可以是连线,如果要区分,可以判断获取的数据里面是否有key属性,节点有key属性,连线有from,to属性。

if(e.subject.part.data.key == undefined){

.......

}

3.监听新拖拽到画布的节点

mySelf.myDiagram.addModelChangedListener(function (evt) {
              if (!evt.isTransactionFinished) return;
              var txn = evt.object;
              if (txn === null) return;
              txn.changes.each(function(e) {
                if (e.modelChange !== "nodeDataArray") return;
                if (e.change === go.ChangedEvent.Insert) {
                  that.selectNode=e.newValue;
                }
              });
            });

4、通过key值去查找节点

mySelf.myDiagram.findNodeForKey(key).data

这里的key值是节点的key值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值