OK, I’ll assume you are using v3, which has support for Routers.
I think this does what I’m guessing you want:
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
<script src="https://cdn.jsdelivr.net/npm/gojs/release/go-debug.js"></script>
<script id="code">
class CurviRouter extends go.Router {
constructor(init) {
super();
this.isRealtime = false;
if (init) Object.assign(this, init);
}
routeLinks(links, coll) {
const allLinks = (coll instanceof go.Diagram ? coll.links : coll.memberParts.filter(p => p instanceof go.Link));
const p = new go.Point();
const intersects = new go.Set();
allLinks.each(link => {
if (link.curve !== go.Curve.Bezier) {
link.curve = go.Curve.Bezier;
link.routing = go.Routing.Normal;
link.fromEndSegmentLength= 35;
link.toEndSegmentLength = 35;
link.updateRoute();
}
intersects.clear();
if (this.doesBezierLinkCrossOverAnotherNode(link, p, intersects)) {
link.curve = go.Curve.None;
link.routing = go.Routing.AvoidsNodes;
link.fromEndSegmentLength= 10;
link.toEndSegmentLength = 10;
link.updateRoute();
}
});
}
// P and INTERSECTS are optional Point and go.Set values,
// to potentially avoid unnecessary memory allocation, and
// to be able to tell which Nodes it crossed over.
doesBezierLinkCrossOverAnotherNode(link, p, intersects) {
if (link.curve !== go.Curve.Bezier) return false;
if (!p) p = new go.Point();
if (!intersects) intersects = new go.Set();
const fromB = link.fromNode.actualBounds;
const toB = link.toNode.actualBounds;
const geo = link.geometry;
const linkB = link.routeBounds;
const intv = 1/(Math.sqrt(linkB.width * linkB.width + linkB.height * linkB.height) / 8);
for (let frac = intv; frac < 1.0; frac += intv) {
geo.getPointAlongPath(frac, p);
p.offset(linkB.x, linkB.y);
// crossing over the fromNode or the toNode is OK
if (fromB.containsPoint(p)) continue;
if (toB.containsPoint(p)) continue;
// see if there are any other Parts at this point
myDiagram.findPartsAt(p, false, intersects);
}
return intersects.any(part => part instanceof go.Node);
}
}
const myDiagram =
new go.Diagram("myDiagramDiv", {
layout: new go.LayeredDigraphLayout(),
"undoManager.isEnabled": true
});
myDiagram.routers.insertAt(0, new CurviRouter()); // takes precedence over AvoidsNodesRouter
myDiagram.nodeTemplate =
new go.Node("Auto")
.add(
new go.Shape({ fill: "white" })
.bind("fill", "color"),
new go.TextBlock({ margin: 8 })
.bind("text")
);
myDiagram.linkTemplate =
new go.Link({
corner: 10, // used when orthogonal
curve: go.Curve.Bezier, fromEndSegmentLength: 35, toEndSegmentLength: 35
})
.add(
new go.Shape(),
new go.Shape({ toArrow: "OpenTriangle" })
);
myDiagram.model = new go.GraphLinksModel({
linkKeyProperty: "key",
nodeDataArray: [
{ key: 1, text: "Alpha", color: "lightblue" },
{ key: 3, text: "Gamma", color: "lightgreen" },
{ key: 4, text: "Delta", color: "pink" },
{ key: 2, text: "Beta", color: "orange" },
],
linkDataArray: [
{ key: "1-2", from: 1, to: 2 },
{ key: "1-3", from: 1, to: 3 },
{ key: "1-4", from: 1, to: 4 },
{ key: "3-4", from: 3, to: 4 },
]
});
</script>
</body>
</html>