Minikarte
Der full-Modus dockt bereits eine Übersicht über das gesamte Diagramm in einer Arbeitsflächeecke an, und eine Zeile – plugins: [minimap()], wie unten – fügt stattdessen in jedem Modus Ihr eigenes konfiguriertes Diagramm dort ein. Klicken irgendwo darin, um die Ansicht dorthin zu bringen; ziehen das Rechteck zum Schwenken. Das Diagramm unten ist breiter als sein Ansichtsfenster, es gibt also eine Möglichkeit. Der kleine Pfeil in der inneren Ecke der Minikarte blendet sie auf genau diese Schaltfläche ein, wenn die Arbeitsfläche wichtiger ist als die Übersicht.
Obwohl es sich um ein Plugin handelt, nicht um integriertes Chrome – der full-Modus installiert es einfach für Sie und steht für die hier übergebene Kopie zur Seite. Es installiert sich über die übergebenen PluginContext und verwendet nichts, was ein eigenes Plugin nicht könnte – es liest die Ausdehnung des Diagramms mit renderer.getContentBounds(), berechnet den sichtbaren Bereich durch Invertieren der Arbeitsflächeecken über renderer.screenToGraphCoordinates() und verschiebt die Ansicht mit renderer.setViewport(). Die gesamte Oberfläche finden Sie unter Plugins.
Es bleibt auch günstig bei einem Diagramm, das tatsächlich eines benötigt. Das Bild befindet sich in einer zwischengespeicherten Bitmap außerhalb des Bildschirms, die nur dann neu gerastert wird, wenn sich das Diagramm ändert (oder bei jedem 10. Simulationstick, während sich ein Layout beruhigt); Durch Schwenken und Zoomen wird ein Bild und ein Rechteck neu gezeichnet, unabhängig von der Anzahl der Knoten. Nach 1.500 Knoten wird das Zeichnen jedes Knotens gestoppt und stattdessen die Dichte gezeichnet, was sich besser lesen lässt als Zehntausende überlappender Punkte und überhaupt keine Stile pro Knoten auflöst.
Zoomen Sie mit den Ansichtsfenster-Steuerelementen hinein und ziehen Sie dann das Rechteck in der Minikarte – das Inhaltsbild wird nie neu gezeichnet, nur das Rechteck wird verschoben.
// import { minimap } from 'pivotick'
const options = {
UI: {
// `full` mode brings a minimap of its own; `light` and `viewer` need asking
// (`UI.minimap: true`, or the plugin below). `static` never has one.
mode: 'full',
// The other thing full mode brings. Off here: this card is about the minimap.
table: false
},
// A plugin installs itself through the PluginContext it is handed — the core never
// needs to know it exists. `graph.use(minimap())` works just as well, at any time.
// Passed here it replaces the one full mode would have mounted, configuration and all.
plugins: [
minimap({
position: 'bottom-right', // the corner the built-in chrome leaves free
width: 220
// height: omitted → follows the canvas's aspect ratio
})
],
render: {
nodeTypeAccessor: (node) => node.getData()?.kind,
nodeStyleMap: {
hub: { color: '#0072B2', size: 13 },
leaf: { color: '#E69F00', size: 7 }
}
},
simulation: {
d3LinkDistance: 60
}
}// A graph deliberately bigger than the viewport, so the minimap has something to
// navigate: six clusters of satellites around a spine.
const nodes = []
const edges = []
const hubs = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta']
hubs.forEach((hub, hubIndex) => {
const angle = (hubIndex / hubs.length) * Math.PI * 2
nodes.push({
id: hub,
data: { name: hub, kind: 'hub' },
x: Math.cos(angle) * 420,
y: Math.sin(angle) * 420
})
if (hubIndex > 0) edges.push({ from: hubs[hubIndex - 1], to: hub })
for (let leafIndex = 0; leafIndex < 9; leafIndex++) {
const id = `${hub}-${leafIndex}`
const spread = (leafIndex / 9) * Math.PI * 2
nodes.push({
id,
data: { name: id, kind: 'leaf' },
x: Math.cos(angle) * 420 + Math.cos(spread) * 130,
y: Math.sin(angle) * 420 + Math.sin(spread) * 130
})
edges.push({ from: hub, to: id })
}
})
const data = { nodes, edges }