ミニマップ
full モードでは、グラフ全体の概要がすでにキャンバスの隅にドッキングされており、 行 — plugins: [minimap()]、以下のように — 代わりに、独自に設定したものをそこに置きます。 どのモードでも。 クリック をクリックして、 そこをご覧ください。長方形をドラッグしてパンします。以下のグラフはビューポートよりも広いため、 行くところがあります。ミニマップの内側の隅にある小さな矢印は、ミニマップを折りたたんで、 概要よりもキャンバスが重要な場合は、このボタンだけで済みます。
それでも、これは プラグイン であり、組み込みクロムではありません — full モードは単にそれをインストールするだけです そして、ここに渡されたコピーを脇に置きます。それはそれ自体を介してインストールされます PluginContext これは渡され、独自のプラグインでは使用できないものは何も使用しません。 renderer.getContentBounds() を使用したグラフの範囲は、次のようにして可視領域を計算します。 キャンバスの角をrenderer.screenToGraphCoordinates()まで反転し、 renderer.setViewport()でご覧ください。表面全体については、プラグインを参照してください。
また、実際に必要なグラフでも安価なままです。画像はキャッシュに保存されています グラフが変更されたとき (または 10 回ごと) にのみ再ラスタライズされるオフスクリーン ビットマップ レイアウトが安定する間のシミュレーション ティック)。パンとズームの再描画 1 つの画像と 1 つの画像 長方形、ノード数に関係なく。 1500 ノードを超えると、各ノードの描画が停止され、 代わりに密度をペイントします。これは、何万ものドットが重なり合うよりも読みやすくなります。 ノードごとのスタイルはまったく解決されません。
ビューポート コントロールを使用してズームインし、ミニマップ内の四角形をドラッグします。 コンテンツの画像は再描画されず、四角形のみが移動します。
// 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 }