2016-02-26 17 views
5

Sto cercando di ottenere la legenda del mio grafico al di fuori dell'area del grafico.d3.js Ottieni legenda fuori dal grafico

Qui ci sono i margini:

var margin = {top: 50, right: 200, bottom: 50, left: 40}; 
     var width = 960 - margin.left - margin.right, 
      height = 500 - margin.top - margin.bottom; 

prima cosa creare lo svg:

var svg = d3.select("body").append("svg") 
      .attr("width", width + margin.left + margin.right) 
      .attr("height", height + margin.top + margin.bottom) 
      .append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

Così, dalla mia comprensione, ora ho l'elemento svg tela e ag all'interno di esso, che detiene il grafico. Sto cercando di aggiungere altro al margine destro, in modo da ottenere un po 'di spazio tra la tela svg e il g aggiunto ad esso, che contiene il grafico. Allora voglio mettere la mia leggenda in quello spazio vuoto.

Qui è dove aggiungo la mia leggenda:

//add legend 
      var legend = svg.append("g") 
       .attr("class", "legend") 
       .attr("height", 300) 
       .attr("width", 200) 
       .attr("transform", "translate(-1000,50"); 

Anche se sto aggiungendo l'elemento SVG, è aggiungendo al g all'interno dell'elemento svg. Quindi, non importa quanto lo traduco o provi a farlo andare più a destra sullo schermo, non supera mai la larghezza della g interna.

Durante la risoluzione dei problemi, vedo che l'elemento SVG esterno ha un'altezza di 960 e una larghezza di 500. Il g aggiunto a quello ha una trasformazione/traduzione di 40,50. La larghezza finisce con 839px per 433.223px (non sono sicuro di averlo capito). Lo svg esterno ha un po 'di spazio a destra ora a causa del margine integrato.

Quindi sto provando ad aumentare la larghezza del g aggiunto alla svg così posso mettere la mia leggenda come figlio di la g e spostarla nello spazio vuoto creato dal margine. Oppure, sto cercando di creare un altro g che è un fratello del primo g e quindi posso usare lo spazio vuoto creato dal margine.

Non riesco né a lavorare né a sapere quale sia la soluzione migliore.

+0

Gli elementi g non hanno attributi di larghezza e altezza, si autorizzano sempre a contenere i propri figli –

+0

La prima istruzione non restituisce lo 'svg', ma restituisce invece l'aggiunta 'g'. Questo è il motivo per cui la tua dichiarazione della leggenda annida la prossima g sotto la prima. d3 usa il metodo di concatenamento, quindi chiamando .append() restituisce la nuova selezione. Correggere rompendo la tua dichiarazione di creazione svg in due istruzioni separate, una creando la 'svg' e poi un'altra creando la 'g' per il tuo grafico. –

risposta

2

Si noti che il var svg viene assegnato ad un <g> nidificato all'interno del <svg>

svg = d3.select("body").append("svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom) 
     .append("g") // <-- This is what svg is currently being assigned to 
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

E così, quando si esegue in seguito var legend = svg.append("g"), si sta effettivamente aggiungendo la leggenda come un bambino del citato <g>. Ed è quello che hai descritto vedendo negli strumenti di sviluppo.

Una conseguenza è che il translate() trasformazione applicata al esterno <g> affetti interno <g> (cioè la traduzione del innter <g> di legend si aggiunge a quella esterna <g>).

Probabilmente, si vuole dividere le cose in questo modo:

var svg = d3.select("body").append("svg") 
      .attr("width", width + margin.left + margin.right) 
      .attr("height", height + margin.top + margin.bottom); 

var inner = svg.append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

quindi modificare il codice per disegnare il grafico esistente in inner piuttosto che svg.

Di conseguenza, var legend = svg.append("g") aggiungerà leggenda come un fratello di inner, e qualsiasi traduzione si applica a legend sarebbe relativo alla parte superiore sinistra del svg (in contrapposizione a in alto a sinistra inner s', che viene tradotto da margin)

E probabile che si desidera tradurre legend in questo modo:

var legend = svg.append("g") 
       .attr("transform", "translate(" + width - margin.right + "," + margin.top + ")"); 

che si muove la leggenda per l'estremità destra del grafico, MENO margin.right. In questo modo, è possibile modificare margin.right per creare spazio sufficiente per legend.

Infine, ricordiamo che chiamando

legend 
    .attr("height", 300) 
    .attr("width", 200) 

non fa nulla, perché per SVG <g>, non c'è un modo per impostare in modo esplicito la larghezza e l'altezza. Ciò non significherebbe comunque molto, perché svg non ha il comportamento "flusso" dei layout html. La larghezza e l'altezza mostrate negli strumenti dev sono i limiti impliciti risultanti dai limiti dei figli di <g>. (Se necessario, c'è un modo per ottenere quei limiti calcolati in javascript, usando la funzione getBBox()).

-1

, cercando in codice che hai fornito, in realtà si sta collegando la leggenda var al gruppo "g", invece di "SVG",
var legend = svg.append("g")

in questa linea si indica d3 per ottenere la variabile leggenda a "g" che si accoda a SVG, se ho capito bene si dovrebbe provare qualcosa di simile:

var legend = svg.selectAll(".legend") 
.enter().append("g") 

per creare un altro gruppo "g" per le leggende. Mi scuso per il mio pessimo inglese.