FYI, normal autoscrolling is invoked for DraggingTool, LinkingTool, and DragSelectingTool. Autoscrolling only happens within the Diagram.autoScrollRegion that is just inside the bounds of the viewport. (Note that it isn’t called padding because that property is in viewport coordinates, not document coordinates.) The reason is that it is moderately common for the mouse drag-and-drop going outside of the viewport to mean doing a drag-and-drop to a different HTML element. So the autoscrolling policy only deals with when the mouse pointer is inside the viewport.
Although Diagram.autoScrollRegion and Diagram.autoScrollInterval are documented, the rest of the API is not. That includes:
- Diagram.doAutoScroll, called by doMouseMove in those tools listed above to start maybe autoscrolling
- Diagram.stopAutoScroll
- Diagram.computeAutoScrollPosition, given a mouse point in viewport coordinates, return the intended new Diagram.position in document coordinates
Although those methods are not documented, they are in the go.d.ts
definitions file. I suppose we could document them, but there is at least one API change I’d want to make first.
It is this last method that you need to override in order to implement your own custom autoscrolling behavior. Or else you can implement everything from scratch – that wouldn’t be too hard, but you might as well use what is already there.
Here’s an example that only autoscrolls by a constant distance when the mouse is outside of the viewport.
[EDIT: oops, I didn’t account for autoscrolling in both x and y directions at once. I have updated this code.]
<!DOCTYPE html>
<html>
<head>
<title>Custom AutoScrolling</title>
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:400px; height:400px"></div>
<script src="https://cdn.jsdelivr.net/npm/gojs/release/go-debug.js"></script>
<script id="code">
class CustomAutoScrollingDiagram extends go.Diagram {
constructor(div, init) {
super(div);
if (init) Object.assign(this, init);
}
computeAutoScrollPosition(vp) {
const pos = this.position;
const sc = this.scale;
const off = 10 / sc;
const vb = this.viewportBounds;
let x = pos.x;
if (vp.x < 0) x -= off;
if (vp.x > vb.width * sc) x += off;
let y = pos.y;
if (vp.y < 0) y -= off;
if (vp.y > vb.height * sc) y += off;
return new go.Point(x, y);
}
}
const myDiagram =
new CustomAutoScrollingDiagram("myDiagramDiv", {
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
new go.Node("Auto")
.add(
new go.Shape({ fill: "white" })
.bind("fill", "color"),
new go.TextBlock({ margin: 8 })
.bind("text")
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", color: "lightblue" },
{ key: 2, text: "Beta", color: "orange" },
{ key: 3, text: "Gamma", color: "lightgreen" },
{ key: 4, text: "Delta", color: "pink" }
],
[
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 2, to: 2 },
{ from: 3, to: 4 },
{ from: 4, to: 1 }
]);
</script>
</body>
</html>