Disposition optimisée automatiquement
Un graphe de cinq nœuds et un graphe de cinq cents nécessitent une physique très différente, tout comme un graphe de petits points par rapport à un graphe de grandes cartes-images. Plutôt que de choisir un ensemble de paramètres de force et d'espérer, Pivotick les dérive de ce qui est réellement à l'écran (nombre de nœuds, taille de nœud, taille du canevas) et les redérive chaque fois que le graphique change. C'est la valeur par défaut.
Développez le graphique ci-dessous et regardez les boutons bouger : la distance de liaison diminue à mesure que la toile devient encombrée, et la traction de centrage augmente pour maintenir le tout dans le cadre.
- Il ne déplace que les boutons que vous pouvez voir. Auto pilote les mêmes commandes que le menu volant Physique, et les curseurs suivent — rien ne se passe derrière un levier caché.
- Vous gagnez toujours. Faites glisser un curseur ou choisissez Tight / Loose, et l'auto s'arrête définitivement ; il ne sera jamais réajusté sur un choix que vous avez fait.
- Il reste calme. Les déclencheurs arrivant ensemble sont fusionnés et un changement trop petit pour être vu est ignoré — donc un pivot qui ajoute quarante nœuds coûte un relais.
- Il ne réveille jamais une simulation en pause.
Auto est activé à moins que le graphique ne configure lui-même une force, donc les configurations existantes conservent la leur. Voir Réglage automatique de la mise en page pour la règle exacte.
// 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' }
}// 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
}// 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()
}
}// 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' }
]
}