自动调整布局
五个节点的图和五百个节点的图需要非常不同的物理特性,小点图与大图像卡的图也是如此。 Pivotick 不是选择一组力设置并希望,而是从屏幕上实际显示的内容(节点数、节点大小、画布大小)派生它们,并在图表发生变化时重新派生它们。这是默认设置。
放大下面的图表并观察旋钮的移动:随着画布变得拥挤,链接距离会下降,而居中拉力会上升以将所有内容保持在框架中。
- 它只移动您可以看到的旋钮。自动驱动与物理弹出按钮相同的控件,并且滑块跟随 - 隐藏杆后面没有任何反应。
- 你总是赢。拖动滑块,或选择紧 / 松,自动停止;它永远不会重新调整您所做的选择。
- 它保持平静。一起到达的触发器被合并,并且跳过太小而无法看到的更改 - 因此添加四十个节点的拓展需要一次重新布局。
- 它永远不会唤醒暂停的模拟。
除非图形本身配置了力,否则“自动”处于打开状态,因此现有设置将保留。具体规则请参见自动布局调整。
js
// Nothing here configures a force, so the layout tunes itself — that is the
// default. `physics: 'auto'` is spelled out only because the documentation
// gallery pins every other example to `'manual'` for stable screenshots.
//
// Setting any force option instead (d3LinkDistance, d3ManyBodyStrength,
// d3CollideRadiusMultiplier, d3VelocityDecay, d3GravityStrength,
// d3GravityStrengthConnected, d3AlphaDecay, cooldownTime) would keep your value
// and switch the tuning off for that graph.
const options = {
simulation: { physics: 'auto' }
}js
// Auto re-tunes on every visible change to the graph, so growing it is all it
// takes to watch the knobs move. Triggers arriving together are coalesced into a
// single pass, and a change too small to matter is skipped entirely — so a pivot
// that adds forty nodes costs one relayout, not forty.
let seq = 0
function addBatch(graph, size = 20) {
const existing = graph.getNodes()
const nodes = []
const edges = []
for (let i = 0; i < size; i++) {
const id = `n-${++seq}`
const pool = existing.concat(nodes)
const parent = pool[Math.floor(Math.random() * pool.length)]
nodes.push({ id, data: { label: id } })
edges.push({ from: parent.id, to: id })
}
graph.updateData(nodes, edges)
}
function reset(graph) {
for (const node of graph.getNodes()) {
if (!data.nodes.some((seed) => seed.id === node.id)) graph.removeNode(node.id)
}
seq = 0
}js
// Auto only ever moves the knobs the Physics flyout exposes, so whatever it
// decided can simply be read back — and overridden by dragging a slider, which
// hands control back to you for good.
function readKnobs(graph) {
const { repulsion, linkDistance, centering } = graph.simulation.getPhysicsKnobs()
return {
nodes: graph.getNodes().length,
repulsion,
linkDistance,
centering,
auto: graph.simulation.isAutoPhysicsEnabled()
}
}js
// A small seed graph — small enough that fixed force settings would leave it
// huddled in the middle of the canvas.
const data = {
nodes: [
{ id: 'core', data: { label: 'core' } },
{ id: 'api', data: { label: 'api' } },
{ id: 'web', data: { label: 'web' } },
{ id: 'db', data: { label: 'db' } },
{ id: 'queue', data: { label: 'queue' } }
],
edges: [
{ from: 'web', to: 'api' },
{ from: 'api', to: 'core' },
{ from: 'core', to: 'db' },
{ from: 'core', to: 'queue' }
]
}