节点模板(nodeTemplate)
当我们没有手动指定节点模板的时候,其实 GoJS
是有默认模板的,也就是我们最开始的例子,一个节点(Node
)加一个文本(TextBlock
)。
默认的节点模板:
我们可以自定义节点的样式
// 创建画布
this.diagram = $(go.Diagram, "diagram",{"undoManager.isEnabled": true});
// 定义模板
this.diagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape,
{ figure: "RoundedRectangle", fill: "white" },
),
$(go.TextBlock,
{ text: "hello!", margin: 20 })
);
// 定义数据
const nodeDataArray = [
{ key: "Alpha" },
{ key: "Beta" },
{ key: "Gamma" }
];
// 创建模型实例
const myModel = new go.Model(nodeDataArray);
// 最终赋值给 diagram.model 修改模型
this.diagram.model = myModel;
自定义的节点模板:
连线模板(linkTemplate)
如果想让图表中的节点之间有一些有向或者无向的连线,仅仅靠普通的 Model
是无法做到的。此时应该使用 TreeModel
或者 GraphLinksModel
。
TreeModel
TreeModel
适用于比较简单的场景。
创建一个 nodeDataArray
数组,用来保存节点数据,每个元素需要增加一个 key
作为唯一标识。
TreeModel
只用 nodeDataArray
一个数组就可以,不需要用一个额外的数组定义连线,只需在定义节点的时候指定父节点即可。
在定义节点同时指定当前节点的父节点,用属性 parent
表示,属性值是节点的 key
值。
特点:只能处理比较简单的连线情况,如果比较复杂就无能为力,比如,一个节点有多个父节点,或者一对节点之间有多条连线的情况。
语法:
const myTreeModel = new go.TreeModel(nodeDataArray);
演示代码:
// 创建画布
this.diagram = $(go.Diagram, "diagram", { "undoManager.isEnabled": true });
// 定义数据
const nodeDataArray = [
{ key: "Head" },
{ key: "Alpha", parent: "Head" },
{ key: "Beta", parent: "Head" },
{ key: "A", parent: "Alpha" },
{ key: "B", parent: "Alpha" },
{ key: "C", parent: "Beta" },
{ key: "D", parent: "Beta" },
{ key: "E", parent: "Beta" },
];
// 创建 TreeModel 模型实例
const myTreeModel = new go.TreeModel(nodeDataArray);
// 最终赋值给 diagram.model 修改模型
this.diagram.model = myTreeModel;
结果如下:
发现连线重合,布局混乱,这时可以使用 TreeLayout
解决。
// 创建画布
this.diagram = $(go.Diagram, "diagram", {
"undoManager.isEnabled": true,
layout: $(go.TreeLayout, { angle: 90, layerSpacing: 35 })
});
// 定义数据
const nodeDataArray = [
{ key: "Head" },
{ key: "Alpha", parent: "Head" },
{ key: "Beta", parent: "Head" },
{ key: "A", parent: "Alpha" },
{ key: "B", parent: "Alpha" },
{ key: "C", parent: "Beta" },
{ key: "D", parent: "Beta" },
{ key: "E", parent: "Beta" },
];
// 创建 TreeModel 模型实例
const myTreeModel = new go.TreeModel(nodeDataArray);
// 最终赋值给 diagram.model 修改模型
this.diagram.model = myTreeModel;
这下就比较正常了。
GraphLinksModel
GraphLinksModel
适用于比较复杂的情况。
创建一个 nodeDataArray
数组,用来保存节点数据,每个元素需要增加一个 key
作为唯一标识。
创建一个 linkDataArray
数组,利用 from
和 to
属性表示连线的指向,它俩的属性值就是节点的 key
值。
语法:
const myGraphLinksModel = new go.GraphLinksModel(nodeDataArray, linkDataArray);
演示代码:
// 创建画布
this.diagram = $(go.Diagram, "diagram", { "undoManager.isEnabled": true });
// 定义节点数据
const nodeDataArray = [
{ key: "Head" },
{ key: "Alpha", parent: "Head" },
{ key: "Beta", parent: "Head" },
{ key: "A", parent: "Alpha" },
{ key: "B", parent: "Alpha" },
{ key: "C", parent: "Beta" },
{ key: "D", parent: "Beta" },
{ key: "E", parent: "Beta" },
];
// 定义连线数据
const linkDataArray = [
{ from: "Alpha", to: "Head" },
{ from: "Beta", to: "Alpha" },
{ from: "A", to: "Alpha" },
{ from: "B", to: "Alpha" },
{ from: "C", to: "Alpha" },
{ from: "D", to: "C" },
{ from: "E", to: "D" },
]
// 创建模型实例
const myGraphLinksModel = new go.GraphLinksModel(nodeDataArray, linkDataArray);
// 最终赋值给 diagram.model 修改模型
this.diagram.model = myGraphLinksModel;
结果如下:
linkTemplate
和节点模板相同的是,我们也可以自定义连线模板。
// 定义连线模板
this.diagram.linkTemplate =
$(go.Link,
{ routing: go.Link.Orthogonal, corner: 5 },
$(go.Shape, { strokeWidth: 3, stroke: "#555" })
)
最后变成了这样:
图表事件(DiagramEvent)
DiagramEvent
表示一般用户发起的对图表的改变。可以通过调用 Diagram.addDiagramListener
注册图表事件处理程序,各个图表事件以名字区分,也可以在图表初始化时调用 go.GraphObject.make
注册图事件处理程序。
常用的的图表事件名称包括:
事件名称 | 事件含义 |
InitialAnimationStarting | 初始默认动画即将开始;不要在事件侦听器中修改图或其模型。这对于修改AnimationManager.defaultAnimation以制作自定义初始动画很有用。 |
AnimationStarting | 一个默认动画(AnimationManager.defaultAnimation)将要开始;不要在事件侦听器中修改图或其模型。 |
AnimationFinished | 刚刚完成的默认动画(AnimationManager.defaultAnimation);不要在事件侦听器中修改图或其模型。 |
BackgroundSingleClicked | 当鼠标左键单击发生在图的背景中而不是零件上时;如果进行任何更改,请启动并提交自己的事务。 |
BackgroundDoubleClicked | 当鼠标左键双击发生在图表的背景中而不是零件上时;如果进行任何更改,请启动并提交自己的事务。 |
BackgroundContextClicked | 当在图的背景中而不是在零件的背景中发生鼠标右键单击时;如果进行任何更改,请启动并提交自己的事务。 |
ChangeingSelection | 一个操作即将更改Diagram.selection集合,该集合也是DiagramEvent.subject的值;不要在事件侦听器中对选择或图表或模型进行任何更改;请注意,仅设置Part.isSelected不会引发此事件,但是工具和命令将引发此事件。 |
ChangedSelection | 一个操作刚刚更改了Diagram.selection集合,该集合也是DiagramEvent.subject的值;不要在事件侦听器中对选择或图表或模型进行任何更改;请注意,仅设置Part.isSelected不会引发此事件,但是工具和命令将引发此事件。 |
ClipboardChanged | 零件已通过CommandHandler.copySelection复制到剪贴板; 所述DiagramEvent.subject是零件的集合; 如果进行任何更改,请启动并提交自己的事务。 |
ClipboardPasted | CommandHandler.pasteSelection已将零件从剪贴板复制到图表中; 该DiagramEvent.subject是Diagram.selection,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
DocumentBoundsChanged | 图的部件的区域Diagram.documentBounds已更改;该DiagramEvent.parameter是旧的矩形。 |
ExternalObjectsDropped | 通过从图的外部拖放将零件复制到图中;该DiagramEvent.subject是一套零件被丢弃的(这也是Diagram.selection),该DiagramEvent.parameter是源图,这是一个事务中调用,这样你就不必从头开始,并提交您的自己的交易。 |
GainedFocus | 该图已获得键盘焦点,诸如一个呼叫后Diagram.focus。 |
InitialLayoutCompleted | 自从对图进行重大更改(例如替换模型)以来,整个图布局首次更新。如果进行任何更改,则无需执行交易。 |
LayoutCompleted | 整个图的布局刚刚更新;如果进行任何更改,则无需执行交易。 |
LinkDrawn | 用户刚刚使用LinkingTool创建了一个新的Link ;该DiagramEvent.subject是新的链接,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务.. |
LinkRelinked | 用户刚刚重新连接使用现有链路RelinkingTool或DraggingTool ; 该DiagramEvent.subject是修改后的链接,该DiagramEvent.parameter是GraphObject端口的链接从断开连接,这就是所谓的事务中,这样你就不必从头开始,并提交自己的事务.. |
LinkReshaped | 用户刚刚使用LinkReshapingTool重新路由了现有的Link ;该DiagramEvent.subject是修改后的链接,该DiagramEvent.parameter是链接的原始路线点的列表,这就是所谓的事务中,这样你就不必从头开始,并提交自己的事务.. |
LostFocus | 该图失去了键盘焦点(“模糊”)。 |
Modified | Diagram.isModified 属性已设置为新值-用于将窗口标记为自上次保存以来已被修改;不要在事件侦听器中修改逻辑示意图或其模型。 |
ObjectSingleClicked | 发生在GraphObject上的点击;该DiagramEvent.subject是GraphObject; 如果进行任何更改,请启动并提交自己的事务。 |
ObjectDoubleClicked | 发生在GraphObject上的双击;该DiagramEvent.subject是GraphObject; 如果进行任何更改,请启动并提交自己的事务。 |
ObjectContextClicked | 发生在GraphObject上的上下文单击;该DiagramEvent.subject是GraphObject; 如果进行任何更改,请启动并提交自己的事务。 |
PartCreated | 用户通过ClickCreatingTool插入了一个新的Part ;该DiagramEvent.subject是新的部分,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
PartResized | 用户已通过ResizingTool更改了GraphObject的大小;该DiagramEvent.subject是GraphObject,该DiagramEvent.parameter是原来的大小,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
PartRotated | 用户通过RotatingTool改变了GraphObject的角度; 该DiagramEvent.subject是GraphObject,该DiagramEvent.parameter是度原来的角度,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SelectionMoved | 用户已通过DraggingTool移动了选定的零件;该DiagramEvent.subject是一套移动零件,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SelectionCopied | 用户已通过DraggingTool复制了选定的零件;该DiagramEvent.subject是新复制件的设置,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SelectionDeleting | 用户将通过CommandHandler.deleteSelection删除选定的部件;该DiagramEvent.subject是Diagram.selection零件的集合被删除,这就是所谓的事务中,这样你就不必从头开始,并提交自己的事务。 |
SelectionDeleted | 用户已通过CommandHandler.deleteSelection删除了选定的部件;该DiagramEvent.subject是被删除的零件的集合,这就是所谓的事务中,这样你就不必从头开始,并提交自己的事务。 |
SelectionGrouped | 用户已通过CommandHandler.groupSelection从选定的零件中创建了一个新的组;该DiagramEvent.subject是新的集团,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SelectionUngrouped | 用户已删除选定的组,但通过CommandHandler.ungroupSelection保留了其成员;该DiagramEvent.subject是被取消组合组的集合,该DiagramEvent.parameter是被取消组合的前成员零件的集合,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SubGraphCollapsed | 用户已通过CommandHandler.collapseSubGraph折叠了选定的组;该DiagramEvent.subject是被压塌的是群体的集合,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
SubGraphExpanded | 用户已通过CommandHandler.expandSubGraph扩展了选定的组;该DiagramEvent.subject是被扩展组的集合,这就是所谓的事务中,这样你就不必从头开始,并提交自己的事务。 |
TextEdited | 用户已通过TextEditingTool更改了TextBlock的字符串值;该DiagramEvent.subject是编辑的TextBlock时,DiagramEvent.parameter是原始的字符串,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
TreeCollapsed | 用户已通过CommandHandler.collapseTree折叠了带有子树的选定节点;该DiagramEvent.subject是被压塌的是节点的集合,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
TreeExpanded | 用户已通过CommandHandler.expandTree用子树扩展了选定的Nodes 。该DiagramEvent.subject是被扩展节点的集合,这是一个事务中调用,这样你就不必从头开始,并提交自己的事务。 |
ViewportBoundsChanged | 图的可见区域Diagram.viewportBounds已更改;所述DiagramEvent.subject是一个对象,其“规模”属性是旧Diagram.scale值,其“位置”属性是旧Diagram.position值,其“范围”属性是旧Diagram.viewportBounds值; 该DiagramEvent.parameter也是老viewportBounds矩形。不要在侦听器中修改图的位置或比例(即视口范围) |