GoJs 将父节点和图表集中在 canvas
GoJs centralize parent node and diagram within the canvas
我正在使用 gojs-angular npm 包,我创建了一个如下图。我需要特别集中我的父节点,但我无法做到这一点。问题是如何集中 AWS 节点
状态会像
public state = {
diagramNodeData: [
{id: '18933', text: "AWS", color: 'lightblue'},
{id: '36082', text: "Track Section", color: 'lightblue'},
{id: '32845', text: "Signalling RAM", color: 'lightblue'},
{id: '32852', text: "Head of Signalling", color: 'lightblue'}
],
diagramLinkData: [
{key: '37537', from: '18933', to: '36082', fromPort: 'r', toPort: 'l', text: "protects"},
{key: '36962', from: '32845', to: '18933', fromPort: 'r', toPort: 'l', text: "repairs"},
{key: '37014', from: '18933', to: '32852', fromPort: 'r', toPort: 'l', text: "owns standard for"}
],
tempDiagramNodeLinks: [],
diagramModelData: {prop: 'value'},
selectedNodeData: null, // used by InspectorComponent
};
我需要中间的 AWS 节点,整个图应该位于这个 DIV 的中心。
我的angularcomponent.ts文件
import {Component, Inject, OnInit} from "@angular/core";
import {DOCUMENT} from "@angular/common";
import * as go from 'gojs';
import {TopologyData} from "../../../../../shared/model/topology-data";
import {SngService} from "../../../../../services/sng.service";
interface NodeElement {
id: string;
text?: string;
color?: string;
}
interface LinkElement {
id: string;
from?: string;
to?: string;
fromPort?: string;
toPort?: string;
text?: string;
}
@Component({
selector: 'gs-sng-network-topology',
template: require('./gs-sng-network-topology.component.html'),
styles: [
require('./gs-sng-network-topology.component.css').toString()
]
})
export class GsSngNetworkTopologyComponent implements OnInit {
topologyData: TopologyData;
private subjectId: string;
private tempDiagramNodeLinks: Array<any> = [];
private tempDiagramLinkDataMap: Map<string, LinkElement> = new Map<string, LinkElement>();
//TODO router replacement required
spcSupGuId: string;
viewGuid: string;
objectGuid: string;
public diagramDivClassName: string = 'sngNetworkDiv';
// Diagram state props
public state = {
diagramNodeData: [],
diagramLinkData: [],
diagramModelData: { prop: 'value' },
skipsDiagramUpdate: false,
selectedNodeData: null, // used by InspectorComponent
};
//TODO router replacement required
constructor(private sngService: SngService,
@Inject(DOCUMENT) private document: Document) {
}
ngOnInit(): void {
this._loc();
this.sngService.getGraphJSON(this.spcSupGuId, this.viewGuid, this.objectGuid)
.subscribe(result => {
this.topologyData = result;
console.log('SNG ', this.topologyData)
this._processData();
});
}
_processData() {
this.subjectId = this.topologyData.graph.subjectId;
this.topologyData.graph.nodes.forEach(node => {
if(node.label == 'DATobject'){
this.state.diagramNodeData.push({id: node.id, text: node.properties?.SUPtitle, color: "lightblue"});
}
else{
this.tempDiagramNodeLinks.push({id: node.id, text: node.properties?.SUPtitle});
}
});
console.log('diagramNodeData :', this.state.diagramNodeData);
console.log('tempDiagramNodeLinks :', this.tempDiagramNodeLinks);
this.topologyData.graph.relationships.forEach(relationship => {
this.tempDiagramNodeLinks.forEach(tempNodeLink => {
if(relationship.endNode == tempNodeLink.id) {
if(relationship.properties?.LNKdirection == 'Start'){
//from
if(this.tempDiagramLinkDataMap.has(tempNodeLink.id)){
let linkElement = this.tempDiagramLinkDataMap.get(tempNodeLink.id);
linkElement.from = relationship.startNode;
}
else{
this.tempDiagramLinkDataMap.set(tempNodeLink.id, {id: tempNodeLink.id, from: relationship.startNode, text: tempNodeLink.text});
}
}
}
else if(relationship.startNode == tempNodeLink.id) {
if(relationship.properties?.LNKdirection == 'End'){
//to
if(this.tempDiagramLinkDataMap.has(tempNodeLink.id)){
let linkElement = this.tempDiagramLinkDataMap.get(tempNodeLink.id);
linkElement.to = relationship.endNode;
}
else{
this.tempDiagramLinkDataMap.set(tempNodeLink.id, {id: tempNodeLink.id, to: relationship.endNode, text: tempNodeLink.text});
}
}
}
else{
console.log('relationship details :', relationship)
}
});
});
console.log('tempDiagramLinkDataMap :', this.tempDiagramLinkDataMap);
this.tempDiagramLinkDataMap.forEach(linkData => {
this.state.diagramLinkData.push(linkData);
})
console.log('state :', this.state);
}
//TODO router replacement required
_loc() {
this.spcSupGuId = this.document.location.href.split('/')[5];
this.viewGuid = this.document.location.href.split('/')[7];
this.objectGuid = this.document.location.href.split('/')[9].split('?')[0];
}
// initialize diagram / templates
public initDiagram(): go.Diagram {
const $ = go.GraphObject.make;
// define diagram
const dia = $(go.Diagram, {
'undoManager.isEnabled': true,
'clickCreatingTool.archetypeNodeData': { text: 'new node', color: 'lightblue' },
layout: $(go.CircularLayout, {spacing: 50}),
model: $(go.GraphLinksModel,
{
nodeKeyProperty: 'id',
linkKeyProperty: 'key' // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
}
)
});
dia.commandHandler.archetypeGroupData = { key: 'Group', isGroup: true };
// define the Node template
dia.nodeTemplate =
$(go.Node, go.Panel.Spot,
{
contextMenu:
$('ContextMenu',
$('ContextMenuButton',
$(go.TextBlock, 'Group'),
{ click: function(e, obj) { e.diagram.commandHandler.groupSelection(); } },
new go.Binding('visible', '', function(o) {
return o.diagram.selection.count > 1;
}).ofObject())
),
locationSpot: go.Spot.Center
},
$(go.Panel, go.Panel.Auto,
$(go.Shape, 'Circle', { stroke: null },
new go.Binding('fill', 'color', (c, panel) => {
return c;
})
),
$(go.TextBlock, { margin: 8, editable: true },
new go.Binding('text').makeTwoWay())
),
);
// define the Link template
dia.linkTemplate = $(go.Link, {curve: go.Link.Bezier}, // Bezier curve
$(go.Shape),
$(go.Shape, {toArrow: "Standard"}), // this is an arrowhead
$(go.Panel, "Auto", // this whole Panel is a link label
$(go.Shape, "RoundedRectangle", {opacity: 1, fill: "white", stroke: "gray"}),
$(go.TextBlock, {margin: 3, editable: false},
new go.Binding("text", "text"))
)
);
dia.grid.visible = true;
return dia;
}
}
我的component.html
<div>
<gojs-diagram #sngNetwork
[divClassName]='diagramDivClassName'
[initDiagram]='initDiagram'
[linkDataArray]='state.diagramLinkData'
[modelData]='state.diagramModelData'
[nodeDataArray]='state.diagramNodeData'>
</gojs-diagram>
</div>
对于任何节点,一旦你有对该节点的引用,你就可以调用:
myDiagram.centerRect(someNode.actualBounds);
要使文档边界居中,您可以调用
myDiagram.alignDocument(go.Spot.Center, go.Spot.Center);
或者直接将图表的 contentAlignment
设置为 go.Spot.Center
。
但是要使 AWS 节点相对于其他节点位于图表的中心,您将需要应用布局或移动节点。
我正在使用 gojs-angular npm 包,我创建了一个如下图。我需要特别集中我的父节点,但我无法做到这一点。问题是如何集中 AWS 节点
状态会像
public state = {
diagramNodeData: [
{id: '18933', text: "AWS", color: 'lightblue'},
{id: '36082', text: "Track Section", color: 'lightblue'},
{id: '32845', text: "Signalling RAM", color: 'lightblue'},
{id: '32852', text: "Head of Signalling", color: 'lightblue'}
],
diagramLinkData: [
{key: '37537', from: '18933', to: '36082', fromPort: 'r', toPort: 'l', text: "protects"},
{key: '36962', from: '32845', to: '18933', fromPort: 'r', toPort: 'l', text: "repairs"},
{key: '37014', from: '18933', to: '32852', fromPort: 'r', toPort: 'l', text: "owns standard for"}
],
tempDiagramNodeLinks: [],
diagramModelData: {prop: 'value'},
selectedNodeData: null, // used by InspectorComponent
};
我需要中间的 AWS 节点,整个图应该位于这个 DIV 的中心。
我的angularcomponent.ts文件
import {Component, Inject, OnInit} from "@angular/core";
import {DOCUMENT} from "@angular/common";
import * as go from 'gojs';
import {TopologyData} from "../../../../../shared/model/topology-data";
import {SngService} from "../../../../../services/sng.service";
interface NodeElement {
id: string;
text?: string;
color?: string;
}
interface LinkElement {
id: string;
from?: string;
to?: string;
fromPort?: string;
toPort?: string;
text?: string;
}
@Component({
selector: 'gs-sng-network-topology',
template: require('./gs-sng-network-topology.component.html'),
styles: [
require('./gs-sng-network-topology.component.css').toString()
]
})
export class GsSngNetworkTopologyComponent implements OnInit {
topologyData: TopologyData;
private subjectId: string;
private tempDiagramNodeLinks: Array<any> = [];
private tempDiagramLinkDataMap: Map<string, LinkElement> = new Map<string, LinkElement>();
//TODO router replacement required
spcSupGuId: string;
viewGuid: string;
objectGuid: string;
public diagramDivClassName: string = 'sngNetworkDiv';
// Diagram state props
public state = {
diagramNodeData: [],
diagramLinkData: [],
diagramModelData: { prop: 'value' },
skipsDiagramUpdate: false,
selectedNodeData: null, // used by InspectorComponent
};
//TODO router replacement required
constructor(private sngService: SngService,
@Inject(DOCUMENT) private document: Document) {
}
ngOnInit(): void {
this._loc();
this.sngService.getGraphJSON(this.spcSupGuId, this.viewGuid, this.objectGuid)
.subscribe(result => {
this.topologyData = result;
console.log('SNG ', this.topologyData)
this._processData();
});
}
_processData() {
this.subjectId = this.topologyData.graph.subjectId;
this.topologyData.graph.nodes.forEach(node => {
if(node.label == 'DATobject'){
this.state.diagramNodeData.push({id: node.id, text: node.properties?.SUPtitle, color: "lightblue"});
}
else{
this.tempDiagramNodeLinks.push({id: node.id, text: node.properties?.SUPtitle});
}
});
console.log('diagramNodeData :', this.state.diagramNodeData);
console.log('tempDiagramNodeLinks :', this.tempDiagramNodeLinks);
this.topologyData.graph.relationships.forEach(relationship => {
this.tempDiagramNodeLinks.forEach(tempNodeLink => {
if(relationship.endNode == tempNodeLink.id) {
if(relationship.properties?.LNKdirection == 'Start'){
//from
if(this.tempDiagramLinkDataMap.has(tempNodeLink.id)){
let linkElement = this.tempDiagramLinkDataMap.get(tempNodeLink.id);
linkElement.from = relationship.startNode;
}
else{
this.tempDiagramLinkDataMap.set(tempNodeLink.id, {id: tempNodeLink.id, from: relationship.startNode, text: tempNodeLink.text});
}
}
}
else if(relationship.startNode == tempNodeLink.id) {
if(relationship.properties?.LNKdirection == 'End'){
//to
if(this.tempDiagramLinkDataMap.has(tempNodeLink.id)){
let linkElement = this.tempDiagramLinkDataMap.get(tempNodeLink.id);
linkElement.to = relationship.endNode;
}
else{
this.tempDiagramLinkDataMap.set(tempNodeLink.id, {id: tempNodeLink.id, to: relationship.endNode, text: tempNodeLink.text});
}
}
}
else{
console.log('relationship details :', relationship)
}
});
});
console.log('tempDiagramLinkDataMap :', this.tempDiagramLinkDataMap);
this.tempDiagramLinkDataMap.forEach(linkData => {
this.state.diagramLinkData.push(linkData);
})
console.log('state :', this.state);
}
//TODO router replacement required
_loc() {
this.spcSupGuId = this.document.location.href.split('/')[5];
this.viewGuid = this.document.location.href.split('/')[7];
this.objectGuid = this.document.location.href.split('/')[9].split('?')[0];
}
// initialize diagram / templates
public initDiagram(): go.Diagram {
const $ = go.GraphObject.make;
// define diagram
const dia = $(go.Diagram, {
'undoManager.isEnabled': true,
'clickCreatingTool.archetypeNodeData': { text: 'new node', color: 'lightblue' },
layout: $(go.CircularLayout, {spacing: 50}),
model: $(go.GraphLinksModel,
{
nodeKeyProperty: 'id',
linkKeyProperty: 'key' // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
}
)
});
dia.commandHandler.archetypeGroupData = { key: 'Group', isGroup: true };
// define the Node template
dia.nodeTemplate =
$(go.Node, go.Panel.Spot,
{
contextMenu:
$('ContextMenu',
$('ContextMenuButton',
$(go.TextBlock, 'Group'),
{ click: function(e, obj) { e.diagram.commandHandler.groupSelection(); } },
new go.Binding('visible', '', function(o) {
return o.diagram.selection.count > 1;
}).ofObject())
),
locationSpot: go.Spot.Center
},
$(go.Panel, go.Panel.Auto,
$(go.Shape, 'Circle', { stroke: null },
new go.Binding('fill', 'color', (c, panel) => {
return c;
})
),
$(go.TextBlock, { margin: 8, editable: true },
new go.Binding('text').makeTwoWay())
),
);
// define the Link template
dia.linkTemplate = $(go.Link, {curve: go.Link.Bezier}, // Bezier curve
$(go.Shape),
$(go.Shape, {toArrow: "Standard"}), // this is an arrowhead
$(go.Panel, "Auto", // this whole Panel is a link label
$(go.Shape, "RoundedRectangle", {opacity: 1, fill: "white", stroke: "gray"}),
$(go.TextBlock, {margin: 3, editable: false},
new go.Binding("text", "text"))
)
);
dia.grid.visible = true;
return dia;
}
}
我的component.html
<div>
<gojs-diagram #sngNetwork
[divClassName]='diagramDivClassName'
[initDiagram]='initDiagram'
[linkDataArray]='state.diagramLinkData'
[modelData]='state.diagramModelData'
[nodeDataArray]='state.diagramNodeData'>
</gojs-diagram>
</div>
对于任何节点,一旦你有对该节点的引用,你就可以调用:
myDiagram.centerRect(someNode.actualBounds);
要使文档边界居中,您可以调用
myDiagram.alignDocument(go.Spot.Center, go.Spot.Center);
或者直接将图表的 contentAlignment
设置为 go.Spot.Center
。
但是要使 AWS 节点相对于其他节点位于图表的中心,您将需要应用布局或移动节点。