本文内容纲要:
- 基础概念
- 开始绘制图形
- 1. 通过代码构建图形
- 2. 通过 GraphObject.make 构建图形
- 3. 使用 Model 和 Templates 创建图形
- 获取图形数据
- 获取所有 Node、Link
- diagram.model.toJSON()
- 获取指定的 Node,Link
- 获取选择元素信息
- 修改图形
- 修改节点属性
- 选中元素
- 删除、添加节点和边
- 事件
- Transactions
- Template Maps
- Palette Diagrams
- 在Vue中使用GOJS
目录
-
基础概念
-
开始绘制图形
- [1. 通过代码构建图形](#1. 通过代码构建图形)
- [2. 通过 GraphObject.make 构建图形](#2. 通过 GraphObject.make 构建图形)
- [3. 使用 Model 和 Templates 创建图形](#3. 使用 Model 和 Templates 创建图形)
-
获取图形数据
- [获取所有 Node、Link](#获取所有 Node、Link)
- diagram.model.toJSON()
- [获取指定的 Node,Link](#获取指定的 Node,Link)
- 获取选择元素信息
-
修改图形
- 修改节点属性
- 选中元素
- 删除、添加节点和边
-
事件
-
Transactions
-
[Template Maps](#Template Maps)
-
[Palette Diagrams](#Palette Diagrams)
-
在Vue中使用GOJS
GoJS 和 GO 语言没有关系,它是一个用来创建交互式图表的 JavaScript 库。
基础概念
GraphObject 是所有图形是抽象基类,基本上 GoJS 中,万物皆 GraphObject。
Panel 有不同的类型,每个类型表示一种布局,通过不同的坐标系统排列。
注意,GoJS 中的 x 轴水平向右,y 轴垂直向下。
包括:
- Panel.Position 建立坐标系,通过指定坐标对绝对位置排序。
- Panel.Vertical & Panel.Horizontal 顾名思义,分别在垂直和水平的线性排列
- Panel.Auto 调整主元素的大小以适应 Panel 中的其他元素。
- Panel.Spot 通过 GraphObject.alignment 属性指定其他元素相对于主元素的位置。
- Panel.Table 以表格的方式排列元素,通过指定 row 和 col 以及相关信息指定元素位置。
- Panel.TableRow & Panel.TableColumn 只能在 Panel.Table 中使用,以将元素集合组织为表格中的行或列。
- Panel.Viewbox 用于自动调整 ** 单个元素 ** 的大小以适合面板的可用区域。
- Panel.Grid 仅用于绘制常规的线条图案。元素必须是用于描述重复行的形状。
- Panel.Link 仅供 Link 部件和 Link Adornments 使用。
- Panel.Graduated 用于沿主 Shape 元素绘制常规刻度线和文本。
Diagram.add
Node 可以被 Link 连接起来。每一个 Node 都有一个 key,用来唯一标识该 Node。link 有 from 和 to 属性,用来表示该 Link 连接了哪两个边。
Group 是一个 Node,可以包含一组 Nodes 和 Links。
Shape 表示一个几何图形。可以使用 GoJS 中定义好的一些图形,如 “Rectangle” 也可以自定义图形的形状。通过 fill 和 stroke 等属性决定图形的显示。
font-style font-variant font-weight font-size font-family
Picture 用来展示图片。
开始绘制图形
1. 通过代码构建图形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://unpkg.com/gojs/release/go.js"></script>
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px blue; width:400px; height:150px"></div>
<script>
// 创建图
var diagram = new go.Diagram("myDiagramDiv");
// 创建节点 节点中元素的排列方式是 Panel.Auto
var node = new go.Node(go.Panel.Auto);
// 创建图形
var shape = new go.Shape();
// 定义图形属性
shape.figure = "RoundedRectangle";
shape.fill = "lightblue";
// 将图形加到节点
node.add(shape);
// 创建一个文本
var textblock = new go.TextBlock();
// 定义文本属性
textblock.text = "Hello!";
textblock.margin = 5;
// 文本加到节点
node.add(textblock);
// 将节点加到图
diagram.add(node);
</script>
</body>
</html>
2. 通过 GraphObject.make 构建图形
GraphObject.makeGraphObject
go.GraphObject.make$
var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.add(
$(go.Node, go.Panel.Auto,
$(go.Shape,
{ figure: "RoundedRectangle", fill: "lightblue" }),
$(go.TextBlock,
{ text: "Hello!", margin: 5 })
));
make
例如,如果 text 写错为 test,会在控制台看到报错:
Uncaught Error: Trying to set undefined property "test" on object: TextBlock("")
3. 使用 Model 和 Templates 创建图形
虽然第二种方式很简单,但是如果要加很多的 Node,而不同的 Node 之间结构相同,通过上面的方式,就需要 add 好多次。如果能定义一个 Node 的模板,然后通过指定参数来定义节点,就会方便很多。
这就类似定义一个类,以后只需要通过 new Something(p1, p2...) 来将创建一类对象。
举例,
var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.nodeTemplate = // 定义模板
$(go.Node, "Auto",
$(go.Shape,
{ figure: "RoundedRectangle", fill: "white" }),
$(go.TextBlock,
{ text: "hello!", margin: 5 })
);
var nodeDataArray = [
{ key: "Alpha" },
{ key: "Beta" }
];
var linkDataArray = [
{ from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
go.GraphLinksModeldiagram.nodeTemplatediagram.model
如果 Node 的结构相同,只是某几个属性不同,也可以在模板中定义变量。变量通过 go.Binding 来定义。
var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.nodeTemplate = // 定义模板
$(go.Node, "Auto",
$(go.Shape,
{ figure: "RoundedRectangle", fill: "white" }, // white 作为 fill 的默认属性
new go.Binding('fill', 'myFill') // 在 model 的 nodes 中通过 myFill 属性来指定 Node 的 fill 属性
),
$(go.TextBlock,
{ text: "hello!", margin: 5 })
);
var nodeDataArray = [
{ key: "Alpha" }, // 默认白色节点
{ key: "Beta", myFill: 'green' } // 绿色节点
];
var linkDataArray = [
{ from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
获取图形数据
获取所有 Node、Link
diagram.model.nodeDataArray
[{"key":"Alpha","__gohashid":408},{"key":"Beta","myFill":"green","__gohashid":409}]
__gohashid
diagram.model.linkDataArray
diagram.nodesIterator
for (var it = diagram.nodes; it.next(); ) {
var node = it.value;
console.log(node);
}
diagram.links
注意,通过 diagram 获得的节点和 model 中的不同,这样获得的节点包含很多图中的其他信息,比如对于边,包含相连的节点信息等。
diagram.model.toJSON()
__gohashid
> diagram.model.toJSON()
< "{ "class": "GraphLinksModel",
"nodeDataArray": [
{"key":"Alpha"},
{"key":"Beta", "myFill":"green"}
],
"linkDataArray": [ {"from":"Alpha", "to":"Beta"} ]
}"
diagram.model = go.Model.fromJson(model);
获取指定的 Node,Link
findNodeDataForKey
> diagram.model.findNodeDataForKey('Alpha')
< {key: "Alpha", __gohashid: 408}
findLinkDataForKeylinkKeyProperty
也可以通过 diagram 查找节点。
> diagram.findNodeForKey('Alpha')
< V {__gohashid: 457, G: 4194307, lb: 1, bg: null, Ua: "", …}
> diagram.findNodeForKey('Alpha').data === diagram.model.findNodeDataForKey('Alpha')
< true
diagram.findLinkForData__gohashid
> diagram.findLinkForData({from: "Alpha", to: "Beta",__gohashid: 411})
< S {__gohashid: 469, G: 4194307, lb: 1, bg: null, Ua: "", …}
> link = diagram.findLinkForData(diagram.model.linkDataArray[0])
< S {__gohashid: 469, G: 4194307, lb: 1, bg: null, Ua: "", …}
> link.data
< {from: "Alpha", to: "Beta", __gohashid: 411}
> link.fromNode
< V {__gohashid: 457, G: 4194307, lb: 1, bg: null, Ua: "", …}
获取选择元素信息
diagram.selection
diagram.selection.size
diagram.selection.first()
修改图形
修改节点属性
modelsetDataProperty
var data = myDiagram.model.findNodeDataForKey("Alpha");
// 直接修改不生效
if (data !== null) data.color = "red";
// 通过 diagram.model.setDataProperty 修改才可以
diagram.model.setDataProperty(data, 'myFill', 'purple');
选中元素
通过代码指定选中元素。
var node = diagram.findNodeForKey('Alpha');
// 会清除当前选中并选中 node
diagram.select(node);
删除、添加节点和边
var node = { key: 'addNode', myFill: 'tomato' };
// 添加节点
diagram.model.addNodeData(node);
// 添加边 Alpha -> addNode
diagram.model.addLinkData({from:'Alpha', to: 'addNode'});
// 删除节点
diagram.model.removeNodeData(node);
事件
Model.addChangedListenerDiagram.addChangedListenerremoveChangedListener
let listener = function(changedEvent) {
// do something...
}
// 添加监听器
diagram.addModelChangedListener(listener);
// 移除监听器
diagram.removeModelChangedListener(listener);
Model.setDataPropertychangedEvent.modelChange
diagram.addModelChangedListener(function(changedEvent) {
// 修改的元素对象(修改后) 修改属性 修改之前的值 修改之后的值
if (changedEvent.modelChange === '') {
console.log(changedEvent.object, changedEvent.propertyName, changedEvent.oldValue, changedEvent.newValue);
}
});
changedEvent.modelChange
Model.nodeDataArraydiagram.model.nodeDataArray = [...]Model.addNodeDataModel.removeNodeDataModel.setCategoryForNodeDataGraphLinksModel.setGroupKeyForNodeDataGraphLinksModel.linkDataArraydiagram.model.nodeDataArray = [...]GraphLinksModel.addLinkDataGraphLinksModel.removeLinkDataGraphLinksModel.setFromKeyForLinkDataGraphLinksModel.setToKeyForLinkDataGraphLinksModel.setFromPortIdForLinkDataGraphLinksModel.setToPortIdForLinkDataGraphLinksModel.setLabelKeysForLinkDataGraphLinksModel.addLabelKeyForLinkDataGraphLinksModel.removeLabelKeyForLinkDataGraphLinksModel.setCategoryForLinkDataTreeModel.setParentKeyForNodeDataTreeModel.setParentLinkCategoryForNodeData
ChangedEvent.propertyNamechangedEvent.modelChange
- "StartingFirstTransaction"
- "StartedTransaction"
- "CommittingTransaction"
- "CommittedTransaction"
- "RolledBackTransaction"
- "StartingUndo"
- "FinishedUndo"
- "StartingRedo"
- "FinishedRedo"
isTransactionFinished
diagram.addModelChangedListener(function(evt) {
if (evt.isTransactionFinished) saveModel(evt.model);
});
Transactions
因为 GoJS 有 undo 和 redo 的功能,所以在撤销和恢复时,要保证单步操作一系列修改的完整性。
但是原则上,每次使用代码来对图形进行修改,都应该用事务包裹起来,即使不开启 undo/redo 功能。
开启 undo & redo 功能 Ctrl-Z(撤销)/ Ctrl-Y(恢复)
diagram.model.undoManager.isEnabled = true;
// 或
diagram =
$(go.Diagram, "myDiagramDiv",
{
"undoManager.isEnabled": true // undo & redo
});
使用事物:
diagram.commit(function(d) {
// ....
}, "do a transaction");
Template Maps
diagram.nodeTemplatemyDiagram.nodeTemplateMapcategory
var template1 =
$(go.Node, "Auto",
$(go.Shape,
{ figure: "RoundedRectangle", fill: "white" }),
$(go.TextBlock,
{ text: "hello!", margin: 5 },
new go.Binding('text', 'text')
));
var template2 =
$(go.Node, "Auto",
$(go.Shape, "RoundedRectangle",
new go.Binding("fill", "color")),
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Left },
$(go.TextBlock, { row: 0, column: 0, columnSpan: 2, font: "bold 12pt sans-serif" },
new go.Binding("text", "key")),
$(go.TextBlock, { row: 1, column: 0 }, "Description:"),
$(go.TextBlock, { row: 1, column: 1 }, new go.Binding("text", "desc")),
$(go.TextBlock, { row: 2, column: 0 }, "Color:"),
$(go.TextBlock, { row: 2, column: 1 }, new go.Binding("text", "color"))
)
);
// 设置 category 为空字符串 则为不指定 category 时的默认图形
diagram.nodeTemplateMap.add('', template1);
// category: detailtemplate
diagram.nodeTemplateMap.add('detailtemplate', template2);
/* 或者定义一个 go.Map 并赋值给 diagram.nodeTemplateMap
var templmap = new go.Map();
templmap.add("", template1);
templmap.add("detailtemplate", template2);
diagram.nodeTemplateMap = templmap;
*/
var nodeDataArray = [
{ key: "Alpha", text: 'Alpha' },
{ key: "Beta", text: 'Beta', color: 'pink', desc: 'desc', category: 'detailtemplate' }
];
var linkDataArray = [
{ from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
Palette Diagrams
创建 go.Palette 来创建图形模板,可以通过拖拽的方式快速生成一系列相同的图案。
在Vue中使用GOJS
官网例子很清晰 不需要赘述
本文内容总结:基础概念,开始绘制图形,1. 通过代码构建图形,2. 通过 GraphObject.make 构建图形,3. 使用 Model 和 Templates 创建图形,获取图形数据,获取所有 Node、Link,diagram.model.toJSON(),获取指定的 Node,Link,获取选择元素信息,修改图形,修改节点属性,选中元素,删除、添加节点和边,事件,Transactions,Template Maps,Palette Diagrams,在Vue中使用GOJS,