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>