Center a picture in a node

Hi,
Please take a look at the attached picture.
The left node has one port. The right node has two ports, one on each side.
Since the left node has only one port , its picture is shifted right and not in the center of the node like the right node which has 2 ports. By the way, if both ports would be on the same side, than, the right node would have shifted too.
How can i force the picture to be in the center of the node, regardless its ports location?

Yes, there are many ways to make sure the picture is in the middle, but it will depend on your node template. What is your current template?


I think i know why. Because the port is located on the node’s outer rectangle.
I will send u the template later.

  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            initialContentAlignment: go.Spot.Center,  // for v1.*
            "undoManager.isEnabled": true
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        $(go.Panel, "Auto",
          $(go.Shape,
            { fill: "white" },
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 18 },
            new go.Binding("text"))
        ),
        $(go.Panel, "Vertical",  // input ports, on left side
          { alignment: go.Spot.Left },
          new go.Binding("itemArray", "ins"),
          {
            itemTemplate:
              $(go.Panel,
                new go.Binding("portId", ""),
                { margin: 1 },
                $(go.Shape, { width: 28, height: 8 })
              )
          }
        ),
        $(go.Panel, "Vertical",  // output ports, on right side
          { alignment: go.Spot.Right },
          new go.Binding("itemArray", "outs"),
          {
            itemTemplate:
              $(go.Panel,
                new go.Binding("portId", ""),
                { margin: 1 },
                $(go.Shape, { width: 28, height: 8 })
              )
          }
        )
      );

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", ins: ["in1", "in2"], outs: ["out1", "out2"] },
      { key: 2, text: "Beta", ins: ["in1"] },
      { key: 3, text: "Gamma", outs: ["out1"] },
      { key: 4, text: "Delta" }
    ]);
  }

produces:
image

I see,
The only problem is that my template manages only one itemArray of ports. The location of each port is either on the left side (spot.x = 0) or on the right side (spot.y=1)
Splitting them into two array requires heavy code change
Here is my templateNode :

defaultNodeTemplate(that) {
var GO = that.GO;
var x =
GO(go.Node, “Spot”,
{
groupable: true,
shadowBlur: 15,
shadowColor: “blue”,
selectionObjectName: “BODY”,
},
// a panel to hold ports on the corner of the rectangle
GO(go.Panel, “Spot”,
GO(go.Shape, “RoundedRectangle”,
{ width: 120, height: 180, fill: “transparent”, strokeDashArray: [2, 5] },
),
new go.Binding(“position”, “loc”, go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding(“itemArray”, “ports”),
{
name: “PortPanel”,
itemTemplate: GO(go.Panel, “Vertical”, // panel to place the textbox (portId) and the port shape (circle) side by side horizontaly
{
toolTip: that.portTooltip(GO),
fromLinkable: true, toLinkable: true,
cursor: “pointer”
},
new go.Binding(“portId”, “portId”),
new go.Binding(“alignment”, “spot”, go.Spot.parse).makeTwoWay(go.Spot.stringify),
// this.createPortShape(that), // the Shape is under the port Name
this.createPortName(that), // port Name
this.createPortAlarm(that), // port Alarm
) // end port dot) // end itemTemplate
},
), // Spot Panel
GO(go.Panel, “Vertical”,
GO(go.Panel, “Spot”,
GO(go.Picture, { width: 50, height: 50, opacity: 1.0 },
new go.Binding(“source”, “source”),
new go.Binding(“width”, “picHeight”),
new go.Binding(“height”, “picWidth”),
new go.Binding(“opacity”, “picOpacity”),
), // Picture
// “deleted” picture, in case an object was deleted
GO(go.Picture, {
//margin :5,
width: 30, height: 30,
opacity: 1.0,
visible: false,
source: NetMapDiagramComponent.CONST_ICON_RELATIVE_PATH + “delete.svg”
},
new go.Binding(“visible”, “isDeleted”)
// )
),
), // go.Panel
GO(go.TextBlock, // Node alarmMessage
{
isMultiline: false, editable: false,
stroke: GO(go.Brush, { color: CONST_DEFAULT_COLOR }),
font: “bold 10pt Verdana sans-serif”,
name: “nodeAlarmMessage”,
background: “white”
},
new go.Binding(“text”, “alarmMessage”),
new go.Binding(“stroke”, “statusColor”),
new go.Binding(“visible”, “alarmMessage”, function (s) { return s != null && s != “” })
),
// Device ID
GO(go.Panel, “Vertical”, new go.Binding(“visible”, “isFullId”).ofModel(), // Panel for Full ID
{ name: “fullIdPanel” },

        GO(go.TextBlock,  // Device Type
          {
            margin: new go.Margin(0, 0, 0, 0),
            isMultiline: false, editable: false,
            stroke: GO(go.Brush, { color: CONST_DEFAULT_COLOR }),
            font: this.CONST_DEFAULT_FONT,
          },
          new go.Binding("text", "deviceType")
        ),
        GO(go.TextBlock,  // ShelfId
          {
            margin: new go.Margin(3, 0, 0, 0),
            isMultiline: false, editable: false,
            stroke: GO(go.Brush, { color: CONST_DEFAULT_COLOR }),
            font: this.CONST_DEFAULT_FONT,
            textAlign: "center"
          },
          new go.Binding("text", "shelfId")
        )
      ),
      GO(go.TextBlock,  // ShortId
        {
          margin: new go.Margin(3, 0, 0, 0),
          //maxSize: new go.Size(150, 50),
          isMultiline: false, editable: false,
          stroke: GO(go.Brush, { color: CONST_DEFAULT_COLOR }),
          font: this.CONST_DEFAULT_FONT,
          visible: false,  // invisible by default
          textAlign: "center"
        },
        new go.Binding("text", "shortId"),
        new go.Binding("visible", "visible", function (s) {
          return !s;
        }).ofObject("fullIdPanel")
      ),  // go.TextBlock

      GO(go.TextBlock,  // for ipAddress
        {
          margin: new go.Margin(3, 0, 0, 0),
          isMultiline: false, editable: false,
          stroke: GO(go.Brush, { color: CONST_DEFAULT_COLOR }),
          font: this.CONST_DEFAULT_FONT,
          textAlign: "center"
        },
        new go.Binding("text", "ipAddress"),
      ),  // go.TextBlock
    )
  );
return x;

}

I cannot really read your code unless you format it properly.

Try this:

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        $(go.Panel, "Auto",
          $(go.Shape,
            { fill: "white" },
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 18 },
            new go.Binding("text"))
        ),
        new go.Binding("itemArray", "ports"),
        {
          itemTemplate:
            $(go.Panel,
              new go.Binding("portId"),
              new go.Binding("alignment", "spot", go.Spot.parse),
              $(go.Shape, { width: 28, height: 8 })
            )
        }
      );

    myDiagram.model = new go.GraphLinksModel(
      [
        {
          key: 1, text: "Alpha",
          ports: [
            { portId: "in1", spot: "0 0.333" },
            { portId: "in2", spot: "0 0.666" },
            { portId: "out1", spot: "1 0.5" }
          ]
        },
        {
          key: 2, text: "Beta",
          ports: [{ portId: "in1", spot: "0 0.5" }]
        },
        {
          key: 3, text: "Gamma",
          ports: [{ portId: "out1", spot: "1 0.5" }]
        },
        { key: 4, text: "Delta" }
      ]);

which produces:
image

I recreated my template based on your template.
Looks fine.
Thanks