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 节点相对于其他节点位于图表的中心,您将需要应用布局或移动节点。