2012-10-23 22 views
10

Sto usando il layout albero D3, come questa: http://mbostock.github.com/d3/talk/20111018/tree.htmlD3 albero separazione verticale

ho modificato per le mie esigenze e sono in esecuzione in un problema. L'esempio ha lo stesso problema in cui, se si hanno troppi nodi aperti, diventano compatti e rende difficile la lettura e l'interazione. Sto volendo definire uno spazio verticale minimo tra i nodi durante il ridimensionamento dello stadio per consentire tale spaziatura.

Ho provato modificando l'algoritmo di separazione per farlo funzionare:

.separation(function (a, b) { 
    return (a.parent == b.parent ? 1 : 2)/a.depth; 
}) 

che non funzionava. Ho anche provato a calcolare quale profondità aveva il maggior numero di bambini, quindi ho detto che l'altezza del palco era children * spaceBetweenNodes. Questo mi ha avvicinato, ma non era ancora preciso.

depthCounts = []; 
nodes.forEach(function(d, i) { 
    d.y = d.depth * 180; 

    if(!depthCounts[d.depth]) 
     depthCounts[d.depth] = 0; 

    if(d.children) 
    { 
     depthCounts[d.depth] += d.children.length; 
    } 
}); 

tree_resize(largest_depth(depthCounts) * spaceBetweenNodes); 

Ho anche cercato di modificare il valore del nodo x anche nel metodo sotto dove calcola la separazione y, ma sigaro. Pubblicherei anche quel cambiamento ma l'ho rimosso dal mio codice.

nodes.forEach(function(d, i) { 
    d.y = d.depth * 180; 
}); 

Se è possibile suggerire un modo o sapere un modo per ottenere una spaziatura minima verticale tra i nodi, si prega di postare. Saró molto grato. Probabilmente mi manca qualcosa di molto semplice.

risposta

4

A partire dal 2016, sono stato in grado di raggiungere questo obiettivo utilizzando solo

tree.nodeSize([height, width]) 

https://github.com/mbostock/d3/wiki/Tree-Layout#nodeSize

L'API di riferimento è un po 'scarsa, ma è opere piuttosto semplice. Assicurati di usarlo dopo lo tree.size([height, width]), altrimenti annullerai nuovamente i tuoi valori.

Per maggiori riferimento: D3 Tree Layout Separation Between Nodes using NodeSize

+0

Grazie, gentile signore !! :) –

4

Sono stato in grado di capirlo con l'aiuto di un utente su Google Gruppi. Non sono riuscito a trovare il post. La soluzione richiede di modificare D3.js in un punto, che non è raccomandato ma è stato l'unico a risolvere questo problema che ho potuto trovare.

partire intorno alla linea 5724 o questo metodo: d3_layout_treeVisitAfter

cambiamento:

d3_layout_treeVisitAfter(root, function(node) { 
    node.x = (node.x - x0)/(x1 - x0) * size[0]; 
    node.y = node.depth/y1 * size[1]; 
    delete node._tree; 
}); 

a:

d3_layout_treeVisitAfter(root, function(node) { 
    // make sure size is null, we will make it null when we create the tree 
    if(size === undefined || size == null) 
    { 
     node.x = (node.x - x0) * elementsize[0]; 
     node.y = node.depth * elementsize[1]; 
    } 
    else 
    { 
     node.x = (node.x - x0)/(x1 - x0) * size[0]; 
     node.y = node.depth/y1 * size[1]; 
    } 
    delete node._tree; 
}); 

Qui di seguito aggiungere una nuova variabile chiamata: elementsize e default a [ 1, 1 ] alla linea 5731

var hierarchy = d3.layout.hierarchy().sort(null).value(null) 
    , separation = d3_layout_treeSeparation 
    , elementsize = [ 1, 1 ] // Right here 
    , size = [ 1, 1 ]; 

seguito che esiste un metodo chiamato tree.size = function(x). Aggiungere il seguente sotto questa definizione:

tree.elementsize = function(x) { 
    if (!arguments.length) return elementsize; 
    elementsize = x; 
    return tree; 
}; 

Infine, quando si crea l'albero è possibile modificare il elementsize in questo modo

var tree = d3.layout.tree() 
      .size(null) 
      .elementsize(50, 240); 
+2

ecco il link di Google Gruppi per ulteriori informazioni https://groups.google.com/forum/?fromgroups#!topic/d3-js/7Js0dGrnyek – Biovisualize

+1

Nella D3 versione 3, c'è ora una proprietà nodeSize che farà la stessa cosa della modifica precedente. Rif: https://github.com/mbostock/d3/wiki/Tree-Layout#nodeDimensioni – patorjk

0

La correzione originale avete proposto funzionerà, devi solo assicurarsi che fare dopo aver aggiunto tutto alla tela. d3 ricalcola il layout ogni volta che entri, esci, accendi, ecc. Una volta che hai fatto tutto, puoi armeggiare con il punto per fissare la profondità.

nodes.forEach(function(d) { d.y = d.depth * fixdepth}); 
2

So che non dovrei rispondere ad altre risposte, ma non ho abbastanza reputazione per aggiungere un commento.

In ogni caso, volevo solo aggiornare questo per le persone che utilizzano l'ultimo file d3.v3.js. (Presumo che ciò sia dovuto a una nuova versione, perché i riferimenti di riga nella risposta accettata erano sbagliati per me.)

La funzione d3.layout.tree che si sta modificando si trova tra le righe 6236 e 6345. d3_layout_treeVisitAfter inizia alla riga 6318. La variabile di gerarchia è dichiarata alla riga 6237. Il bit su tree.elementsize rimane valido - L'ho messo sulla riga 6343.

Infine (presumo che si sia verificato un errore): quando si crea l'albero, si mette le dimensioni all'interno di parentesi quadre, come fai normalmente con "dimensione". Quindi:

var tree = d3.layout.tree() 
     .size(null) 
     .elementsize([50, 240]); 
+0

Se si utilizza la versione 3, non è necessario apportare la modifica. Esiste già una proprietà nodeSize che può essere utilizzata al posto di elementsize. – patorjk

Problemi correlati