Gojs Zoom Issue

I want the HTML box to zoom along with my diagram when I zoom in. Currently, the HTML box does not zoom. Please make it zoom as well. Alternatively, you can add a scrollbar to my node.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>Move GoJS Node via External HTML Box</title>
  <script src="https://unpkg.com/gojs/release/go.js"></script>
  <style>
    body {
      font-family: sans-serif;
    }

    #myDiagramDiv {
      width: 800px;
      height: 500px;
      border: 1px solid black;
      position: relative;
      margin-bottom: 1rem;
    }

    #box3 {
      position: absolute;
      width: 10rem;
      height: 10rem;
      overflow: auto;
      padding: 0.5rem;
      border-radius: 5px;
      background-color: #DB4437;
      color: white;
      font-size: 0.85rem;
      font-weight: bold;
      word-break: break-word;
      z-index: 10000;
      border: 2px solid yellow;
      box-sizing: border-box;
      pointer-events: auto;
      user-select: none;
      cursor: grab;
    }
  </style>
</head>

<body>

  <h2>Drag External HTML Box to Move Node 3</h2>

  <div id="myDiagramDiv"></div>

  <div id="box3">
    Scrollable content for Node 3.<br />
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br /><br />
    Scroll me!<br /><br />
    More content here to make scrolling necessary.
  </div>

  <script>
    const $ = go.GraphObject.make;

    const myDiagram = $(go.Diagram, "myDiagramDiv", {
      "undoManager.isEnabled": true,
      layout: $(go.LayeredDigraphLayout, { direction: 0 })
    });

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Shape, { fill: "lightblue" }),
        $(go.TextBlock, { margin: 8 }, new go.Binding("text", "name"))
      );

    myDiagram.model = new go.GraphLinksModel(
      [
        { key: 1, name: "Node 1", loc: "100 100" },
        { key: 2, name: "Node 2", loc: "250 100" },
        { key: 3, name: "Node 3", loc: "400 100" }
      ],
      [
        { from: 1, to: 2 },
        { from: 2, to: 3 }
      ]
    );

    const box = document.getElementById("box3");

    function syncBoxToNode() {
      const node = myDiagram.findNodeForKey(3);
      if (!node) return;
      const center = node.actualBounds.center;
      const point = myDiagram.transformDocToView(center);
      box.style.left = (point.x - box.offsetWidth / 2) + "px";
      box.style.top = (point.y - box.offsetHeight / 2) + "px";
    }

    // Sync box when diagram changes view or layout
    myDiagram.addDiagramListener("InitialLayoutCompleted", syncBoxToNode);
    myDiagram.addDiagramListener("ViewportBoundsChanged", () => {
      requestAnimationFrame(syncBoxToNode);
    });

    window.addEventListener("load", syncBoxToNode);

    // Drag logic
    (() => {
      let isDragging = false;
      let offsetX = 0;
      let offsetY = 0;

      box.addEventListener('mousedown', (e) => {
        // Only start drag if scrollbar not clicked
        const boxRect = box.getBoundingClientRect();
        if (e.offsetX > box.clientWidth || e.offsetY > box.clientHeight) return;

        isDragging = true;
        offsetX = e.clientX - box.offsetLeft;
        offsetY = e.clientY - box.offsetTop;
        box.style.cursor = 'grabbing';
        e.preventDefault();
      });

      document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;

        const newLeft = e.clientX - offsetX;
        const newTop = e.clientY - offsetY;

        // Update external box position
        box.style.left = newLeft + "px";
        box.style.top = newTop + "px";

        // Compute center of box in diagram view
        const viewX = newLeft + box.offsetWidth / 2;
        const viewY = newTop + box.offsetHeight / 2;
        const docPoint = myDiagram.transformViewToDoc(new go.Point(viewX, viewY));

        // Move node only if location has changed
        const node = myDiagram.findNodeForKey(3);
        if (node && !node.location.equals(docPoint)) {
          myDiagram.model.startTransaction("move node");
          node.location = docPoint;
          myDiagram.model.commitTransaction("move node");
        }
      });

      document.addEventListener('mouseup', () => {
        if (isDragging) {
          isDragging = false;
          box.style.cursor = 'grab';
        }
      });
    })();
  </script>

</body>

</html>

You can detect changes to the Diagram.scale by implementing a “ViewportBoundsChanged” DiagramEvent listener that checks whether the scale has changed:

new go.Diagram(. . ., {
    "ViewportBoundsChanged": e => {
      if (e.diagram.scale !== e.subject.scale) {
        . . . // do whatever you need to do to update the position and scale of your HTML element
      }
    },
    . . .
  });

You might want to do that updating even more often than whenever the value of Diagram.scale changes, such as when the user scrolls the diagram. You seem to be doing that already in your syncBoxToNode function.

[EDIT] Oh, are you asking how to scale an HTML element? That’s not a GoJS question, but basically you want to apply the scale CSS transform. scale() - CSS | MDN