zoukankan      html  css  js  c++  java
  • GOJS使用--前端拓扑图

    GOJS使用--前端拓扑图

    1.基础版:

    • 引入go.js

      <script src="./js/go.js" type="text/javascript"></script>
      
    • 定义html标签

      <!--每个go.js图都包含在html元素中,我们需要给出一个显示的大小-->
      <div id="myDiagramDiv" style="400px; height:150px;background-color: #DAE4E4"></div>
      
    • js

      <script>
          // make构建gojs对象,使$缩写go.GraphObject
          var $ = go.GraphObject.make;
          // JS中,绘制图标时需要传递html标签的ID
          var myDiagram = $(go.Diagram, "myDiagramDiv",
              {
                  "undoManager.isEnabled": true //启动ctrl+z撤销 和 ctrk+y 重做
              }
          );
          // 在模型数据中,每个节点都由一个JavaScript对象表示
          var Mymodel = $(go.Model);
          Mymodel.nodeDataArray = [
              {key: "Alpha"},
              {key: "Beta"},
              {key: "Gamma"},
          ];
          myDiagram.model = Mymodel
      </script>
      
    • 效果如下显示:可以在go.js图的范围内任意拖动三个模块,但是不难发现html上多了几行水印:

    • 去除水印方式:

      在go.js搜索7eba17a4ca3b1a8346
      # 注释掉该行
      a.zr = b.V[Ra("7eba17a4ca3b1a8346")][Ra("78a118b7")](b.V, Ik, 4, 4);
      # 下一行添加
      a.zr = function(){return true;}
      

    2.拓扑图模块添置图片

    • js

      <script>
          // make构建gojs对象,使$缩写go.GraphObject
          var $ = go.GraphObject.make;
          // JS中,绘制图标时需要传递html标签的ID
          var myDiagram = $(go.Diagram, "myDiagramDiv",
              {
                  "undoManager.isEnabled": true //启动ctrl+z撤销 和 ctrk+y 重做
              }
          );
          // 定义node
          myDiagram.nodeTemplate =
              $(go.Node, "Horizontal",
                  // 添加北京颜色 此为当前节点对象
                  {background:"#44CCFF"},
                  $(go.Picture,
                      // 图片的宽高,包括图片背景(在未设置情况下显示)
                      {margin:10,50,height:50,background:"red"},
                      // Picture.source 绑定模型数据source属性的数据
                      new go.Binding("source")
                  ),
                  $(go.TextBlock,
                      // TextBlock.text初始值
                      "默认值..",
                      // 文本一些样式设置字体颜色,字体大小。。。
                      {margin:12,stroke:"white",font:"bold 16px sans-serif"},
                      // TextBlock.text 是绑定到模型数据的 name属性的数据
                      new go.Binding("text","name")
                  )
              );
          // 在模型数据中,每个节点都由一个JavaScript对象表示
          var Mymodel = $(go.Model);
          Mymodel.nodeDataArray = [
              {name: "Alpha", "source":"img/cat1.png"},
              {name: "Beta", "source":"img/cat2.png"},
              {name: "Gamma", "source":"img/cat2.png"},
              {/* Emoty node data */}
          ];
          myDiagram.model = Mymodel
      </script>
      
    • 显示效果:

    3.添置连接线

    • 只需要将Model模型改成TreeModel.并将定义每条数据key和parent来确定每个节点之间关系。

      // key 和oarent来确定每个节点之间关系
      var Mymodel = $(go.TreeModel);
          Mymodel.nodeDataArray = [
              {name: "Alpha", "source":"img/cat1.png", key:"1"},
              {name: "Beta", "source":"img/cat2.png", key:"2", parent:"1"},
              {name: "Gamma", "source":"img/cat2.png", key:"3",parent:"1"},
          ];
      
    • 显示效果

    4.图标布局 树形结构先似乎

    • 需要定义layout.来构建树形结构

      <script>
          // make构建gojs对象,使$缩写go.GraphObject
          var $ = go.GraphObject.make;
          // JS中,绘制图标时需要传递html标签的ID
          var myDiagram = $(go.Diagram, "myDiagramDiv",
              {
                  "undoManager.isEnabled": true, //启动ctrl+z撤销 和 ctrk+y 重做
                  // 指定一个树形结构:从上到下
                  // TreeLayout 默认未从左到右流动,当设置90从上到下,当设置180,从右向左,当设置270表示从下到上
                  // layerSpacing 实行结构每一层的间距
                  layout: $(go.TreeLayout,
                      {angle:90,layerSpacing:50}
                  )
              }
          );
          // 定义node
          myDiagram.nodeTemplate =
              $(go.Node, "Horizontal",
                  // 添加北京颜色 此为当前节点对象
                  {background:"#44CCFF"},
                  $(go.Picture,
                      // 图片的宽高,包括图片背景(在未设置情况下显示)
                      {margin:10,50,height:50,background:"red"},
                      // Picture.source 绑定模型数据source属性的数据
                      new go.Binding("source")
                  ),
                  $(go.TextBlock,
                      // TextBlock.text初始值
                      "默认值..",
                      // 文本一些样式设置字体颜色,字体大小。。。
                      {margin:12,stroke:"white",font:"bold 16px sans-serif"},
                      // TextBlock.text 是绑定到模型数据的 name属性的数据
                      new go.Binding("text","name")
                  )
              );
          // 在模型数据中,每个节点都由一个JavaScript对象表示
          var Mymodel = $(go.TreeModel);
          Mymodel.nodeDataArray = [
              {name: "Alpha", "source":"img/cat1.png", key:"1"},
              {name: "Beta", "source":"img/cat2.png", key:"2", parent:"1"},
              {name: "Gamma", "source":"img/cat3.png", key:"3",parent:"1"},
              {name: "Jellylorum", "source":"img/cat4.png", key:"4",parent:"3"},
              {name: "Alonzo", "source":"img/cat5.png", key:"5",parent:"3"},
              {name: "Munkustrap", "source":"img/cat6.png", key:"6",parent:"2"},
          ];
          myDiagram.model = Mymodel
      </script>
      
    • 显示效果

    5.链接模式

    • 需要定义路线模板和箭头模板

      <script>
          // make构建gojs对象,使$缩写go.GraphObject
          var $ = go.GraphObject.make;
          // JS中,绘制图标时需要传递html标签的ID
          var myDiagram = $(go.Diagram, "myDiagramDiv",
              {
                  "undoManager.isEnabled": true, //启动ctrl+z撤销 和 ctrk+y 重做
                  // 指定一个树形结构:从上到下
                  // TreeLayout 默认未从左到右流动,当设置90从上到下,当设置180,从右向左,当设置270表示从下到上
                  // layerSpacing 实行结构每一层的间距
                  layout: $(go.TreeLayout,
                      {angle:90,layerSpacing:50}
                  )
              }
          );
          // 定义node
          myDiagram.nodeTemplate =
              $(go.Node, "Horizontal",
                  // 添加北京颜色 此为当前节点对象
                  {background:"#44CCFF"},
                  $(go.Picture,
                      // 图片的宽高,包括图片背景(在未设置情况下显示)
                      {margin:10,50,height:50,background:"red"},
                      // Picture.source 绑定模型数据source属性的数据
                      new go.Binding("source")
                  ),
                  $(go.TextBlock,
                      // TextBlock.text初始值
                      "默认值..",
                      // 文本一些样式设置字体颜色,字体大小。。。
                      {margin:12,stroke:"white",font:"bold 16px sans-serif"},
                      // TextBlock.text 是绑定到模型数据的 name属性的数据
                      new go.Binding("text","name")
                  )
              );
          // 定义一个有箭头路线模板
          myDiagram.linkTemplate =
              $(go.Link,
                  // routing默认未go.Link.Normal
                  // corner 为转角值,就是线置交转交的弧度
                  {routing:go.Link.Orthogonal, corner:5},
                  // strokeWidth 线的粗细,stroke 线的颜色
                  $(go.Shape,{strokeWidth:3, stroke: "#555"}),
                  // 生成箭头模板toArrow:Standard,OpenTriangle... stroke为箭头颜色
                  $(go.Shape,{toArrow:"Standard",stroke:null})
              );
          // 在模型数据中,每个节点都由一个JavaScript对象表示
          var Mymodel = $(go.TreeModel);
          Mymodel.nodeDataArray = [
              {name: "Alpha", "source":"img/cat1.png", key:"1"},
              {name: "Beta", "source":"img/cat2.png", key:"2", parent:"1"},
              {name: "Gamma", "source":"img/cat3.png", key:"3",parent:"1"},
              {name: "Jellylorum", "source":"img/cat4.png", key:"4",parent:"3"},
              {name: "Alonzo", "source":"img/cat5.png", key:"5",parent:"3"},
              {name: "Munkustrap", "source":"img/cat6.png", key:"6",parent:"2"},
          ];
          myDiagram.model = Mymodel
      </script>
      
      
    • 显示效果:

    6.自定义:

    • js版本:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title>Flowchart</title>
          <meta name="description" content="Interactive flowchart diagram implemented by GoJS in JavaScript for HTML."/>
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
      
          <script src="./js/go.js"></script>
          <link href='https://fonts.googleapis.com/css?family=Lato:300,400,700' rel='stylesheet' type='text/css'>
          <!--<script src="../assets/js/goSamples.js"></script>  &lt;!&ndash; this is only for the GoJS Samples framework &ndash;&gt;-->
          <script id="code">
              function init() {
                  // 初始化示例
                  // if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
                  // make构建模板
                  var $ = go.GraphObject.make;  // for conciseness in defining templates
                  myDiagram =
                      $(go.Diagram, document.getElementById("myDiagramDiv"),  // must name or refer to the DIV HTML element
                          {
                              // 每次画线后调用的事件:为条件连线加上标签
                              "LinkDrawn": showLinkLabel,  // this DiagramEvent listener is defined below
                              // 每次重画线后调用的事件
                              "LinkRelinked": showLinkLabel,
                              // 启用Ctrl-Z和Ctrl-Y撤销重做功能
                              "undoManager.isEnabled": true,  // enable undo & redo
                              // 居中显示内容
                              initialContentAlignment: go.Spot.Center,
                              // 是否允许从Palette面板拖入元素
                              allowDrop: true,
                          });
      
                  // 当图有改动时,在页面标题后加*,且启动保存按钮
                  myDiagram.addDiagramListener("Modified", function (e) {
                      var button = document.getElementById("SaveButton");
                      if (button) button.disabled = !myDiagram.isModified;
                      var idx = document.title.indexOf("*");
                      if (myDiagram.isModified) {
                          if (idx < 0) document.title += "*";
                      } else {
                          if (idx >= 0) document.title = document.title.substr(0, idx);
                      }
                  });
                  // 设置节点位置风格,并与模型"loc"属性绑定,该方法会在初始化各种节点模板时使用
                  function nodeStyle() {
                      return [
                          // 将节点位置信息 Node.location 同节点模型数据中 "loc" 属性绑定:
                          // 节点位置信息从 节点模型 "loc" 属性获取, 并由静态方法 Point.parse 解析.
                          // 如果节点位置改变了, 会自动更新节点模型中"loc"属性, 并由 Point.stringify 方法转化为字符串
                          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
                          {
                              // 节点位置 Node.location 定位在节点的中心
                              locationSpot: go.Spot.Center
                          }
                      ];
                  }
                  // 创建"port"方法,"port"是一个透明的长方形细长图块,在每个节点的四个边界上,如果鼠标移到节点某个边界上,它会高亮
                  // "name": "port" ID,即GraphObject.portId,
                  // "align": 决定"port" 属于节点4条边的哪条
                  // "spot": 控制连线连入/连出的位置,如go.Spot.Top指, go.Spot.TopSide
                  // "output" / "input": 布尔型,指定是否允许连线从此"port"连入或连出
                  function makePort(name, align, spot, output, input) {
                      // 表示如果是上,下,边界则是水平的"port"
                      var horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
                      return $(go.Shape,
                          {
                              fill: "transparent",  // 默认透明不现实
                              strokeWidth: 0,  // 无边框
                               horizontal ? NaN : 8,  // 垂直"port"则8像素宽
                              height: !horizontal ? NaN : 8,  // 水平"port"则8像素
                              alignment: align,  // 同其节点对齐
                              stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),//自动同其节点一同伸缩
                              portId: name,  // 声明ID
                              fromSpot: spot,  // 声明连线头连出此"port"的位置
                              fromLinkable: output,  // 布尔型,是否允许连线从此"port"连出
                              toSpot: spot,  // 声明连线尾连入此"port"的位置
                              toLinkable: input,  // 布尔型,是否允许连线从此"port"连出
                              cursor: "pointer",  // 鼠标由指针改为手指,表示此处可点击生成连线
                              mouseEnter: function (e, port) {  //鼠标移到"port"位置后,高亮
                                  if (!e.diagram.isReadOnly) port.fill = "rgba(255,0,255,0.5)";
                              },
                              mouseLeave: function (e, port) {// 鼠标移出"port"位置后,透明
                                  port.fill = "transparent";
                              }
                          });
                  }
                  // 定义图形上的文字风格
                  function textStyle() {
                      return {
                          font: "bold 11pt Lato, Helvetica, Arial, sans-serif",
                          stroke: "#F8F8F8"
                      }
                  }
      
                  // 定义步骤(默认类型)节点的模板
      
                  myDiagram.nodeTemplateMap.add("",  // the default category
                      $(go.Node, "Table", nodeStyle(),
                          // 步骤节点是一个包含可编辑文字块的长方形图块
                          $(go.Panel, "Auto",
                              $(go.Shape, "Rectangle",
                                  {fill: "#282c34", stroke: "#00A9C9", strokeWidth: 3.5},
                                  new go.Binding("figure", "figure")),
                              $(go.TextBlock, textStyle(),
                                  {
                                      margin: 8,
                                      maxSize: new go.Size(160, NaN),
                                      wrap: go.TextBlock.WrapFit,// 尺寸自适应
                                      editable: true// 文字可编辑
                                  },
                                  new go.Binding("text").makeTwoWay())// 双向绑定模型中"text"属性
                          ),
                          // 上、左、右可以入,左、右、下可以出
                          // "Top"表示中心,"TopSide"表示上方任一位置,自动选择
                          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)
                      ));
                  // 定义条件节点的模板
                  myDiagram.nodeTemplateMap.add("Conditional",
                      $(go.Node, "Table", nodeStyle(),
                          // 条件节点是一个包含可编辑文字块的菱形图块
                          $(go.Panel, "Auto",
                              $(go.Shape, "Diamond",
                                  {fill: "#282c34", stroke: "#00A9C9", strokeWidth: 3.5},
                                  new go.Binding("figure", "figure")),
                              $(go.TextBlock, textStyle(),
                                  {
                                      margin: 8,
                                      maxSize: new go.Size(160, NaN),
                                      wrap: go.TextBlock.WrapFit,
                                      editable: true
                                  },
                                  new go.Binding("text").makeTwoWay())
                          ),
                          // 上、左、右可以入,左、右、下可以出
                          makePort("T", go.Spot.Top, go.Spot.Top, false, true),
                          makePort("L", go.Spot.Left, go.Spot.Left, true, true),
                          makePort("R", go.Spot.Right, go.Spot.Right, true, true),
                          makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
                      ));
                  // 定义开始节点的模板
                  myDiagram.nodeTemplateMap.add("Start",
                      $(go.Node, "Table", nodeStyle(),
                          $(go.Panel, "Spot",
                              $(go.Shape, "Circle",
                                  {desiredSize: new go.Size(70, 70), fill: "#282c34", stroke: "#09d3ac", strokeWidth: 3.5}),
                              $(go.TextBlock, "Start", textStyle(),
                                  new go.Binding("text"))
                          ),
                          // 左、右、下可以出,但都不可入
                          makePort("L", go.Spot.Left, go.Spot.Left, true, false),
                          makePort("R", go.Spot.Right, go.Spot.Right, true, false),
                          makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
                      ));
                  // 定义结束节点的模板
                  myDiagram.nodeTemplateMap.add("End",
                      $(go.Node, "Table", nodeStyle(),
                          // 结束节点是一个圆形图块,文字不可编辑
                          $(go.Panel, "Spot",
                              $(go.Shape, "Circle",
                                  {desiredSize: new go.Size(60, 60), fill: "#282c34", stroke: "#DC3C00", strokeWidth: 3.5}),
                              $(go.TextBlock, "End", textStyle(),
                                  new go.Binding("text"))
                          ),
                          // 上、左、右可以入,但都不可出
                          makePort("T", go.Spot.Top, go.Spot.Top, false, true),
                          makePort("L", go.Spot.Left, go.Spot.Left, false, true),
                          makePort("R", go.Spot.Right, go.Spot.Right, false, true)
                      ));
      
                  // taken from ../extensions/Figures.js:
                  go.Shape.defineFigureGenerator("File", function (shape, w, h) {
                      var geo = new go.Geometry();
                      var fig = new go.PathFigure(0, 0, true); // starting point
                      geo.add(fig);
                      fig.add(new go.PathSegment(go.PathSegment.Line, .75 * w, 0));
                      fig.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
                      fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
                      fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
                      var fig2 = new go.PathFigure(.75 * w, 0, false);
                      geo.add(fig2);
                      // The Fold
                      fig2.add(new go.PathSegment(go.PathSegment.Line, .75 * w, .25 * h));
                      fig2.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
                      geo.spot1 = new go.Spot(0, .25);
                      geo.spot2 = go.Spot.BottomRight;
                      return geo;
                  });
                   // 定义注释节点的模板
                  myDiagram.nodeTemplateMap.add("Comment",
                      // 注释节点是一个包含可编辑文字块的文件图块
                      $(go.Node, "Auto", nodeStyle(),
                          $(go.Shape, "File",
                              {fill: "#282c34", stroke: "#DEE0A3", strokeWidth: 3}),
                          $(go.TextBlock, textStyle(),
                              {
                                  margin: 8,
                                  maxSize: new go.Size(200, NaN),
                                  wrap: go.TextBlock.WrapFit,// 尺寸自适应
                                  textAlign: "center",
                                  editable: true// 文字可编辑
                              },
                              new go.Binding("text").makeTwoWay())
                          // 不支持连线入和出
                      ));
      
      
                  // 初始化连接线的模板
                  myDiagram.linkTemplate =
                      $(go.Link,  // 所有连接线
                          {
                              routing: go.Link.AvoidsNodes,// 连接线避开节点
                              curve: go.Link.JumpOver,
                              corner: 5, toShortLength: 4,// 直角弧度,箭头弧度
                              relinkableFrom: true,// 允许连线头重设
                              relinkableTo: true,// 允许连线尾重设
                              reshapable: true,// 允许线形修改
                              resegmentable: true,// 允许连线分割(折线)修改
                              // 鼠标移到连线上后高亮
                              mouseEnter: function (e, link) {
                                  link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)";
                              },
                              mouseLeave: function (e, link) {
                                  link.findObject("HIGHLIGHT").stroke = "transparent";
                              },
                              selectionAdorned: false
                          },
                          new go.Binding("points").makeTwoWay(), // 双向绑定模型中"points"数组属性
                          $(go.Shape,  // 隐藏的连线形状,8个像素粗细,当鼠标移上后显示
                              {isPanelMain: true, strokeWidth: 8, stroke: "transparent", name: "HIGHLIGHT"}),
                          $(go.Shape,  // 连线规格(颜色,选中/非选中,粗细)
                              {isPanelMain: true, stroke: "gray", strokeWidth: 2},
                              new go.Binding("stroke", "isSelected", function (sel) {
                                  return sel ? "dodgerblue" : "gray";
                              }).ofObject()),
                          $(go.Shape,   // 箭头规格
                              {toArrow: "standard", strokeWidth: 0, fill: "gray"}),
                          $(go.Panel, "Auto",  // 连线标签,默认不显示
                              {visible: false, name: "LABEL", segmentIndex: 2, segmentFraction: 0.5},
                              new go.Binding("visible", "visible").makeTwoWay(),// 双向绑定模型中"visible"属性
                              $(go.Shape, "RoundedRectangle",  // 连线中显示的标签形状
                                  {fill: "#F8F8F8", strokeWidth: 0}),
                              $(go.TextBlock, "Yes",  // // 连线中显示的默认标签文字
                                  {
                                      textAlign: "center",
                                      font: "10pt helvetica, arial, sans-serif",
                                      stroke: "#333333",
                                      editable: true
                                  },
                                  new go.Binding("text").makeTwoWay()) // 双向绑定模型中"text"属性
                          )
                      );
      
                  // 此事件方法由整个画板的LinkDrawn和LinkRelinked事件触发
                  // 如果连线是从"conditional"条件节点出发,则将连线上的标签显示出来
                  function showLinkLabel(e) {
                      var label = e.subject.findObject("LABEL");
                      if (label !== null) label.visible = (e.subject.fromNode.data.category === "Conditional");
                  }
      
                  // 临时的连线(还在画图中),包括重连的连线,都保持直角
                  myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
                  myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
      
                  load();  // load an initial diagram from some JSON text
      
                  // 在图形页面的左边初始化图例Palette面板
                  myPalette =
                      $(go.Palette, "myPaletteDiv", // 必须同HTML中Div元素id一致
                          {
                              // Instead of the default animation, use a custom fade-down
                              "animationManager.initialAnimationStyle": go.AnimationManager.None,
                              "InitialAnimationStarting": animateFadeDown, // 使用此函数设置动画
      
                              nodeTemplateMap: myDiagram.nodeTemplateMap,  // 同myDiagram公用一种node节点模板
                              model: new go.GraphLinksModel([  // 初始化Palette面板里的内容
                                  {category: "Start", text: "Start"},
                                  {text: "Step"},
                                  {category: "Conditional", text: "???"},
                                  {category: "End", text: "End"},
                                  {category: "Comment", text: "Comment"}
                              ])
                          });
      
                  // 动画效果
                  function animateFadeDown(e) {
                      var diagram = e.diagram;
                      var animation = new go.Animation();
                      animation.isViewportUnconstrained = true; // So Diagram positioning rules let the animation start off-screen
                      animation.easing = go.Animation.EaseOutExpo;
                      animation.duration = 900;
                      // Fade "down", in other words, fade in from above
                      animation.add(diagram, 'position', diagram.position.copy().offset(0, 200), diagram.position);
                      animation.add(diagram, 'opacity', 0, 1);
                      animation.start();
                  }
      
              } // end init
              // 将go模型以JSon格式保存在文本框内
              function save() {
                  document.getElementById("mySavedModel").value = myDiagram.model.toJson();
                  myDiagram.isModified = false;
              }
              // 初始化模型范例
              function load() {
                  myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
              }
      
              // 在新窗口中将图形转化为SVG,并分页打印
              function printDiagram() {
                  var svgWindow = window.open();
                  if (!svgWindow) return;  // failure to open a new Window
                  var printSize = new go.Size(700, 960);
                  var bnds = myDiagram.documentBounds;
                  var x = bnds.x;
                  var y = bnds.y;
                  while (y < bnds.bottom) {
                      while (x < bnds.right) {
                          var svg = myDiagram.makeSVG({scale: 1.0, position: new go.Point(x, y), size: printSize});
                          svgWindow.document.body.appendChild(svg);
                          x += printSize.width;
                      }
                      x = bnds.x;
                      y += printSize.height;
                  }
                  setTimeout(function () {
                      svgWindow.print();
                  }, 1);
              }
          </script>
      </head>
          <body onload="init()">
              <div id="sample">
                  <div style=" 100%; display: flex; justify-content: space-between">
                      <div id="myPaletteDiv" style=" 100px; margin-right: 2px; background-color: #282c34;"></div>
                      <div id="myDiagramDiv" style="flex-grow: 1; height: 750px; background-color: #282c34;"></div>
                  </div>
                  <button id="SaveButton" onclick="save()">Save</button>
                  <button onclick="load()">Load</button>
                  Diagram Model saved in JSON format:
                  <textarea id="mySavedModel" style="100%;height:300px">
                      { "class": "go.GraphLinksModel",
                        "linkFromPortIdProperty": "fromPort",
                        "linkToPortIdProperty": "toPort",
                        "nodeDataArray": [
                       ],
                        "linkDataArray": [
                       ]}
                  </textarea>
                  <button onclick="printDiagram()">Print Diagram Using SVG</button>
              </div>
          </body>
      </html>
      
      
    • vue版

      <template>
        <el-card>
          <my-bread level1='拓扑图' level2='拓扑图绘制'></my-bread>
          <div id='sample'>
            <div style=' 100%; display: flex; justify-content: space-between'>
              <div ref='myPaletteDiv' style=' 100px; margin-right: 2px; background-color: #282c34;'></div>
              <div ref='myDiagramDiv' style='flex-grow: 1; height: 750px; background-color: #282c34;'></div>
            </div>
            <button id='SaveButton' @click='save()'>Save</button>
            <button @click='load()'>Load</button>
            Diagram Model saved in JSON format:
            <textarea ref='mySavedModel' style='100%;height:300px'>
                      {{this.diagramData}}
                  </textarea>
            <button @click='printDiagram()'>Print Diagram Using SVG</button>
          </div>
        </el-card>
      <!--  <button @click='init()'></button>-->
      </template>
      
      <script>
      import go from 'gojs'
      let $ = go.GraphObject.make
      export default {
        data () {
          return {
            diagramData : { 'class': 'go.GraphLinksModel',
              'linkFromPortIdProperty': 'fromPort',
              'linkToPortIdProperty': 'toPort',
              'nodeDataArray': [
              ],
              'linkDataArray': [
              ]},
            myDiagram: null,
            myPalette: null
          }
        },
        mounted () {
          this.myDiagram =
            $(go.Diagram, this.$refs.myDiagramDiv,
              {
                // 每次画线后调用的事件:为条件连线加上标签
                'LinkDrawn': this.showLinkLabel,
                // 每次重画线后调用的事件
                'LinkRelinked': this.showLinkLabel,
                // 启用Ctrl-Z和Ctrl-Y撤销重做功能
                'undoManager.isEnabled': true,
                // 居中显示内容
                initialContentAlignment: go.Spot.Center,
                // 是否允许从Palette面板拖入元素
                allowDrop: true,
              })
          // console.log(this.$refs.SaveButton)
          // 当图有改动时,在页面标题后加*,且启动保存按钮
          // this.myDiagram.addDiagramListener('Modified', function (e) {
          //   // var button = this.$refs.SaveButton
          //   var button = document.getElementById('SaveButton')
          //   if (button) button.disabled =! this.myDiagram.isModified
          //   var idx = document.title.indexOf('*')
          //   if (this.myDiagram.isModified) {
          //     if (idx < 0) document.title += '*'
          //   } else {
          //     if (idx >= 0) document.title = document.title.substr(0, idx)
          //   }
          // })
          // 定义步骤(默认类型)节点的模板
          this.myDiagram.nodeTemplateMap.add('',
            $(go.Node, 'Table', this.nodeStyle(),
              // 步骤节点是一个包含可编辑文字块的长方形图块
              $(go.Panel, 'Auto',
                $(go.Shape, 'Rectangle',
                  {fill: '#282c34', stroke: '#00A9C9', strokeWidth: 3.5},
                  new go.Binding('figure', 'figure')),
                $(go.TextBlock, this.textStyle(),
                  {
                    margin: 8,
                    maxSize: new go.Size(160, NaN),
                    wrap: go.TextBlock.WrapFit,// 尺寸自适应
                    editable: true// 文字可编辑
                  },
                  new go.Binding('text').makeTwoWay())// 双向绑定模型中'text'属性
              ),
              // 上、左、右可以入,左、右、下可以出
              // 'Top'表示中心,'TopSide'表示上方任一位置,自动选择
              this.makePort('T', go.Spot.Top, go.Spot.TopSide, false, true),
              this.makePort('L', go.Spot.Left, go.Spot.LeftSide, true, true),
              this.makePort('R', go.Spot.Right, go.Spot.RightSide, true, true),
              this.makePort('B', go.Spot.Bottom, go.Spot.BottomSide, true, false)
            ))
          // 定义条件节点的模板
          this.myDiagram.nodeTemplateMap.add('Conditional',
            $(go.Node, 'Table', this.nodeStyle(),
              // 条件节点是一个包含可编辑文字块的菱形图块
              $(go.Panel, 'Auto',
                $(go.Shape, 'Diamond',
                  {fill: '#282c34', stroke: '#00A9C9', strokeWidth: 3.5},
                  new go.Binding('figure', 'figure')),
                $(go.TextBlock, this.textStyle(),
                  {
                    margin: 8,
                    maxSize: new go.Size(160, NaN),
                    wrap: go.TextBlock.WrapFit,
                    editable: true
                  },
                  new go.Binding('text').makeTwoWay())
              ),
              // 上、左、右可以入,左、右、下可以出
              this.makePort('T', go.Spot.Top, go.Spot.Top, false, true),
              this.makePort('L', go.Spot.Left, go.Spot.Left, true, true),
              this.makePort('R', go.Spot.Right, go.Spot.Right, true, true),
              this.makePort('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
            ))
            // 定义开始节点的模板
          this.myDiagram.nodeTemplateMap.add('Start',
            $(go.Node, 'Table', this.nodeStyle(),
              $(go.Panel, 'Spot',
                $(go.Shape, 'Circle',
                  {desiredSize: new go.Size(70, 70), fill: '#282c34', stroke: '#09d3ac', strokeWidth: 3.5}),
                $(go.TextBlock, 'Start', this.textStyle(),
                  new go.Binding('text'))
              ),
              // 左、右、下可以出,但都不可入
              this.makePort('L', go.Spot.Left, go.Spot.Left, true, false),
              this.makePort('R', go.Spot.Right, go.Spot.Right, true, false),
              this.makePort('B', go.Spot.Bottom, go.Spot.Bottom, true, false)
            ))
          // 定义结束节点的模板
          this.myDiagram.nodeTemplateMap.add('End',
            $(go.Node, 'Table', this.nodeStyle(),
              // 结束节点是一个圆形图块,文字不可编辑
              $(go.Panel, 'Spot',
                $(go.Shape, 'Circle',
                  {desiredSize: new go.Size(60, 60), fill: '#282c34', stroke: '#DC3C00', strokeWidth: 3.5}),
                $(go.TextBlock, 'End', this.textStyle(),
                  new go.Binding('text'))
              ),
              // 上、左、右可以入,但都不可出
              this.makePort('T', go.Spot.Top, go.Spot.Top, false, true),
              this.makePort('L', go.Spot.Left, go.Spot.Left, false, true),
              this.makePort('R', go.Spot.Right, go.Spot.Right, false, true)
            ));
          // taken from
          go.Shape.defineFigureGenerator('File', function (shape, w, h) {
            var geo = new go.Geometry();
            var fig = new go.PathFigure(0, 0, true); // starting point
            geo.add(fig);
            fig.add(new go.PathSegment(go.PathSegment.Line, .75 * w, 0));
            fig.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
            fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
            fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
            var fig2 = new go.PathFigure(.75 * w, 0, false);
            geo.add(fig2);
            // The Fold
            fig2.add(new go.PathSegment(go.PathSegment.Line, .75 * w, .25 * h));
            fig2.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
            geo.spot1 = new go.Spot(0, .25);
            geo.spot2 = go.Spot.BottomRight;
            return geo;
          })
          // 定义注释节点的模板
          this.myDiagram.nodeTemplateMap.add('Comment',
            // 注释节点是一个包含可编辑文字块的文件图块
            $(go.Node, 'Auto', this.nodeStyle(),
              $(go.Shape, 'File',
                {fill: '#282c34', stroke: '#DEE0A3', strokeWidth: 3}),
              $(go.TextBlock, this.textStyle(),
                {
                  margin: 8,
                  maxSize: new go.Size(200, NaN),
                  wrap: go.TextBlock.WrapFit,// 尺寸自适应
                  textAlign: 'center',
                  editable: true// 文字可编辑
                },
                new go.Binding('text').makeTwoWay())
              // 不支持连线入和出
            ))
          // 初始化连接线的模板
          this.myDiagram.linkTemplate =
            $(go.Link,  // 所有连接线
              {
                routing: go.Link.AvoidsNodes,// 连接线避开节点
                curve: go.Link.JumpOver,
                corner: 5, toShortLength: 4,// 直角弧度,箭头弧度
                relinkableFrom: true,// 允许连线头重设
                relinkableTo: true,// 允许连线尾重设
                reshapable: true,// 允许线形修改
                resegmentable: true,// 允许连线分割(折线)修改
                // 鼠标移到连线上后高亮
                mouseEnter: function (e, link) {
                  link.findObject('HIGHLIGHT').stroke = 'rgba(30,144,255,0.2)';
                },
                mouseLeave: function (e, link) {
                  link.findObject('HIGHLIGHT').stroke = 'transparent';
                },
                selectionAdorned: false
              },
              new go.Binding('points').makeTwoWay(), // 双向绑定模型中'points'数组属性
              $(go.Shape,  // 隐藏的连线形状,8个像素粗细,当鼠标移上后显示
                {isPanelMain: true, strokeWidth: 8, stroke: 'transparent', name: 'HIGHLIGHT'}),
              $(go.Shape,  // 连线规格(颜色,选中/非选中,粗细)
                {isPanelMain: true, stroke: 'gray', strokeWidth: 2},
                new go.Binding('stroke', 'isSelected', function (sel) {
                  return sel ? 'dodgerblue' : 'gray';
                }).ofObject()),
              $(go.Shape,   // 箭头规格
                {toArrow: 'standard', strokeWidth: 0, fill: 'gray'}),
              $(go.Panel, 'Auto',  // 连线标签,默认不显示
                {visible: false, name: 'LABEL', segmentIndex: 2, segmentFraction: 0.5},
                new go.Binding('visible', 'visible').makeTwoWay(),// 双向绑定模型中'visible'属性
                $(go.Shape, 'RoundedRectangle',  // 连线中显示的标签形状
                  {fill: '#F8F8F8', strokeWidth: 0}),
                $(go.TextBlock, 'Yes',  // // 连线中显示的默认标签文字
                  {
                    textAlign: 'center',
                    font: '10pt helvetica, arial, sans-serif',
                    stroke: '#333333',
                    editable: true
                  },
                  new go.Binding('text').makeTwoWay()) // 双向绑定模型中'text'属性
              )
            );
          // 临时的连线(还在画图中),包括重连的连线,都保持直角
          this.myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
          this.myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
          // 读取json数据
          this.load()
          // 在图形页面的左边初始化图例Palette面板
          this.myPalette =
            $(go.Palette, this.$refs.myPaletteDiv, // 必须同HTML中Div元素id一致
              {
                // Instead of the default animation, use a custom fade-down
                'animationManager.initialAnimationStyle': go.AnimationManager.None,
                'InitialAnimationStarting': this.animateFadeDown, // 使用此函数设置动画
      
                nodeTemplateMap: this.myDiagram.nodeTemplateMap,  // 同myDiagram公用一种node节点模板
                model: new go.GraphLinksModel([  // 初始化Palette面板里的内容
                  {category: 'Start', text: '开始'},
                  {text: '步骤'},
                  {category: 'Conditional', text: '选择'},
                  {category: 'End', text: '结束'},
                  {category: 'Comment', text: '标识'}
                ])
              })
        },
        methods : {
          showLinkLabel (e) {
            var label = e.subject.findObject('LABEL')
            if (label !== null) label.visible = (e.subject.fromNode.data.category === 'Conditional')
          },
          // 设置节点位置风格,并与模型'loc'属性绑定,该方法会在初始化各种节点模板时使用
          nodeStyle () {
            return [
              // 将节点位置信息 Node.location 同节点模型数据中 'loc' 属性绑定:
              // 节点位置信息从 节点模型 'loc' 属性获取, 并由静态方法 Point.parse 解析.
              // 如果节点位置改变了, 会自动更新节点模型中'loc'属性, 并由 Point.stringify 方法转化为字符串
              new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
              {
                // 节点位置 Node.location 定位在节点的中心
                locationSpot: go.Spot.Center
              }
            ]
          },
          // 创建'port'方法,'port'是一个透明的长方形细长图块,在每个节点的四个边界上,如果鼠标移到节点某个边界上,它会高亮
          // 'name': 'port' ID,即GraphObject.portId,
          // 'align': 决定'port' 属于节点4条边的哪条
          // 'spot': 控制连线连入/连出的位置,如go.Spot.Top指, go.Spot.TopSide
          // 'output' / 'input': 布尔型,指定是否允许连线从此'port'连入或连出
          makePort (name, align, spot, output, input) {
            // 表示如果是上,下,边界则是水平的'port'
            var horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
            return $(go.Shape,
              {
                fill: 'transparent',  // 默认透明不现实
                strokeWidth: 0,  // 无边框
                 horizontal ? NaN : 8,  // 垂直'port'则8像素宽
                height: !horizontal ? NaN : 8,  // 水平'port'则8像素
                alignment: align,  // 同其节点对齐
                stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),//自动同其节点一同伸缩
                portId: name,  // 声明ID
                fromSpot: spot,  // 声明连线头连出此'port'的位置
                fromLinkable: output,  // 布尔型,是否允许连线从此'port'连出
                toSpot: spot,  // 声明连线尾连入此'port'的位置
                toLinkable: input,  // 布尔型,是否允许连线从此'port'连出
                cursor: 'pointer',  // 鼠标由指针改为手指,表示此处可点击生成连线
                mouseEnter: function (e, port) {  //鼠标移到'port'位置后,高亮
                  if (!e.diagram.isReadOnly) port.fill = 'rgba(255,0,255,0.5)';
                },
                mouseLeave: function (e, port) {// 鼠标移出'port'位置后,透明
                  port.fill = 'transparent';
                }
              })
          },
          // 定义图形上的文字风格
          textStyle() {
            return {
              font: 'bold 11pt Lato, Helvetica, Arial, sans-serif',
              stroke: '#F8F8F8'
            }
          },
          load () {
            this.myDiagram.model = go.Model.fromJson(this.$refs.mySavedModel.value)
            // console.log(this.$refs.mySavedModel.value)
          },
          animateFadeDown(e) {
            var diagram = e.diagram;
            var animation = new go.Animation();
            animation.isViewportUnconstrained = true; // So Diagram positioning rules let the animation start off-screen
            animation.easing = go.Animation.EaseOutExpo;
            animation.duration = 900;
            // Fade 'down', in other words, fade in from above
            animation.add(diagram, 'position', diagram.position.copy().offset(0, 200), diagram.position);
            animation.add(diagram, 'opacity', 0, 1);
            animation.start();
          },
          // 初始化模型范例
          save () {
            this.$refs.mySavedModel.value = this.myDiagram.model.toJson()
            this.myDiagram.isModified = false
          },
          // 在新窗口中将图形转化为SVG,并分页打印
          printDiagram() {
            var svgWindow = window.open();
            if (!svgWindow) return;  // failure to open a new Window
            var printSize = new go.Size(700, 960);
            var bnds = this.myDiagram.documentBounds;
            var x = bnds.x;
            var y = bnds.y;
            while (y < bnds.bottom) {
              while (x < bnds.right) {
                var svg = this.myDiagram.makeSVG({scale: 1.0, position: new go.Point(x, y), size: printSize});
                svgWindow.document.body.appendChild(svg);
                x += printSize.width;
              }
              x = bnds.x;
              y += printSize.height;
            }
            setTimeout(function () {
              svgWindow.print();
            }, 1);
          }
        }
      }
      </script>
      <style scoped>
      
      </style>
      
      
    • 参考文件:

    http://www.bjhee.com/gojs.html

    https://github.com/NorthwoodsSoftware/GoJS

  • 相关阅读:
    CF261E Maxim and Calculator
    USACO Section 2.1
    码工新人的成长升职之路~
    Skip level 1 on 1
    有效利用1 on 1
    [职场感言] 入职一年总结
    职场新人建议
    L1 正则为什么会使参数偏向稀疏
    Inception网络
    ResNet
  • 原文地址:https://www.cnblogs.com/xujunkai/p/12585052.html
Copyright © 2011-2022 走看看