Zu viele Nodes sprengen den Rahmen des SVG-Layouts. Dann ist hineinzoomen in den Graphen sinnvoll und auch das Bewegen des sichtbaren Ausschnitts. Mit den passenden D3-Methoden ist das einfach.

Zunächst brauchen wir eine Variable und eine Methode für den Zoom sowie eine root-Gruppe, in der sich alle node- und link-Elemente befinden. Zoom und Bewegung werden nachher über die root-Gruppe ausgeführt. Jedes darin liegende Element wird entsprechend mit behandelt. Im Zoom wird das Bewegen mit implementiert.
// - - - - - - - - - -
// declaration
// - - - - - - - - - -
let
...
root = undefined,
zoom = undefined,
...
setRoot = undefined,
setZoom = undefined,
...;
Das Definieren des Zooms ist einfach. d3.zoom() wird konfiguriert und an eine SVG-Gruppe (root) gehängt. Es steuert das transform-Attribute über die Werte für translate() für das Bewegen und scale() für das hinein- oder herauszoomen. Auslöser ist das zoom-Ereignis, das (auf meinem MacBook) mit dem Touchpad ausgelöst wird - zoomen mit zwei Fingern und bewegen mit gedrücktem Pad und eben bewegen. (Mausrad und linke Taste gehen natürlich auch).
// - - - - - - - - - -
// functions
// - - - - - - - - - -
setZoom = function () {
zoom = d3.zoom()
.scaleExtent([1 / 4, 4])
.on('zoom', function () {
root.attr('transform',
'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ')' +
'scale(' + d3.event.transform.k + ')');
});
}
Hinzufügen der setRoot-Funktion. Die node- und link-Gruppen werden für das Zooming in eine gemeinsame Gruppe mit der ID root verpackt.
setRoot = function (id) {
root = svg.append('g')
.attr('id', id);
};
...
// building the links
link = root.append("g")
.attr("class", "links")
.selectAll("line")
...
// building the nodes by circles
groupData = root.selectAll()
.data(graph.nodes);
Bei Ausführen der einzelnen Methoden muss nun setZoom() zuerst gesetzt werden.
// - - - - - - - - - -
// control
// - - - - - - - - - -
setZoom();
setCanvas('#diagram'),
setRoot('#root');
Damit es am Ende funktioniert, muss das svg-Objekt die zoom-Methode aufrufen. Das geht über ein call(zoom) am Ende der Befehlskette.
setCanvas = function (contextSelector) {
svg = d3.select(contextSelector)
.append('svg')
.attr('width', canvas.width)
.attr('height', canvas.height)
.attr('viewbox', canvas.viewbox.x + ' ' + canvas.viewbox.y + ' ' + canvas.viewbox.width + ' ' + canvas.viewbox.height)
.call(zoom);
};