GOJS使用--前端拓扑图
1.基础版:
- 引入go.js
<script src="./js/go.js" type="text/javascript"></script>
- 定义html标签
<!--每个go.js图都包含在html元素中,我们需要给出一个显示的大小-->
<div id="myDiagramDiv" style="width: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,width: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,width: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,width: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> <!– this is only for the GoJS Samples framework –>-->
<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, // 无边框
width: 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="width: 100%; display: flex; justify-content: space-between">
<div id="myPaletteDiv" style="width: 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="width: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='width: 100%; display: flex; justify-content: space-between'>
<div ref='myPaletteDiv' style='width: 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='width: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, // 无边框
width: 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