小地图
full 模式已经将整个图表的概述停靠在画布角落中,并且一行 - plugins: [minimap()],如下所示 - 在任何模式下将您自己配置的线放在那里。 单击任意位置即可将视图带到那里; 拖动矩形进行平移。下图比它的视口更宽,所以还有地方可以去。当画布比概览更重要时,小地图内角的小箭头会将其折叠到该按钮上。
Even so it is a plugin, not built-in chrome — full mode simply installs it for you, and stands aside for the copy passed here. It installs itself through the PluginContext it is handed and uses nothing a plugin of your own couldn't — it reads the graph's extent with renderer.getContentBounds(), works out the visible region by inverting the canvas corners through renderer.screenToGraphCoordinates(), and moves the view with renderer.setViewport().整个界面请参见插件。
它在实际需要的图表上也保持便宜。 The picture lives in a cached offscreen bitmap that is only re-rasterised when the graph changes (or every 10th simulation tick while a layout settles);平移和缩放重绘一张图像和一个矩形,无论节点数量如何。 Past 1500 nodes it stops drawing each node and paints density instead, which reads better than tens of thousands of overlapping dots and resolves no per-node styles at all.
使用视口控件进行放大,然后拖动小地图中的矩形 - 内容图片不会重绘,只有矩形会移动。
// 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 }