2015-12-28 27 views
5

Sto cercando di ottenere d3 per disegnare un singolo grafico a barre in pila, in questo modo:d3 come fare tracciare un'unica colonna in pila

<svg width = '500' height= '100'> 
 
<rect x='0' y='0' width='224' height='30' fill='green'/> 
 
<rect x='224' y='0' width='84' height='30' fill='blue'/> 
 
<rect x='308' y='0' width='29' height='30' fill='darkgray'/> 
 
<rect x='337' y='0' width='3' height='30' fill='#606060'/> 
 
</svg>

Come si può vedere, la posizione x inizia da zero, quindi ogni successiva posizione x è uguale alla somma delle larghezze precedenti.

Così sto cercando di ottenere d3 a disegnare qualcosa di simile da un array chiamato datavars:

var datavars = [224, 84, 29, 3]; 

... e per garantire che d3 assegna la larghezza-valore corretto al corretto valore x , ho creato queste variabili:

var prev_width0 = 0; 
var prev_width1 = datavars[0]; 
var prev_width2 = datavars[0] + datavars[1]; 
var prev_width3 = datavars[0] + datavars[1] + datavars[2]; 

... e definire il valore x in questo modo:

//create SVG element 
var svg = d3.select('body') 
.append('svg') 
.attr('width', w) 
.attr('height', h); 

svg.selectAll('rect') 
.data(datavars) 
.enter() 
.append('rect') 
.attr('width', function(d){ 
    return d;}) 
       .attr('x',function(d, i){ 
       return 'prev_width'+i; }) 
.attr('y',0) 
.attr('height', 30); 

come si potrebbe aver indovinato, la funzione fortemente indentata (basata sulla somma delle larghezze precedenti e definita nelle variabili prev_width) restituisce una stringa per ogni iterazione (prev_width0, prev_width1, ecc.) e non i valori che pensavo di definire quando ho creato le variabili prev_width.

Sto ovviamente definendo le variabili in modo errato. Qualche idea su come posso farlo correttamente?

risposta

4

JavaScript non interpreta la stringa "datavars1" come variabile datavars1. Per interpretare una stringa come variabile JavaScript è possibile utilizzare eval(). Quindi modificare: return 'prev_width'+i; }) a return eval('prev_width'+i); }). Anche se una migliore idea potrebbe essere quella di utilizzare un array invece come ad esempio:

var prev_width = [0, 
        datavars[0], 
        datavars[0] + datavars[1], 
        datavars[0] + datavars[1] + datavars[2] 
       ]; 

... 
    .attr('x',function(d, i){ 
    return prev_width[i]; }) 

Fiddle Example

si può fare una cosa simile con i colori:

var colors = ['green','blue','darkgray','#606060']; 

... 
.attr('fill', function(d, i){ return colors[i]; }) 

Bar chart with color

Puoi creare anche una singola matrice di oggetti per memorizzare il colore, la larghezza, ecc.


Un'idea più scalabile sarebbe quella di eliminare l'array prev_width e avere una funzione che può portare la somma fino a un punto.Come ad esempio:

allora si può fare:

... 
    .attr('x',function(d, i){ 
    return sum(datavars, 0, i); }) 

Example using summation

+2

ah ... questi sono molto carini, grazie mille. Il tuo primo suggerimento è quello a cui stavo lottando, e le prossime sono molto più eleganti. Molto apprezzato – prokaryote

0

Ecco un frammento (avvicinato un po 'diverso da me)

//this function deals with pairing finding x for each width in the array and add them to a new array called x_and_width_values 
 
//example :[[0,224],[84,224],[29,308],[3,337]] 
 
//   ^^ ^^^^^^ 
 
//   x width x width ............. 
 
function combinations(prev,current,index,arr){ 
 
// This method focus on accummulating results by reference previous and current element 
 
//for the first and second element we need specifically add this 
 
if(index==1){ 
 
x_and_width_values.push([arr[index-1],0]); 
 
x_and_width_values.push([arr[index],prev]) 
 
} 
 
//other elements we use index as follows; 
 
else{ 
 
x_and_width_values.push([arr[index],prev]) 
 
} 
 
return prev+current 
 
} 
 
//after creating an array with all [x,width] combination, we map it to colors to get out final array 
 
//example :[[[0,224],'green'],[[84,224],'blue'],[29,308],[[3,337],'darkgray'] 
 
function colors_with_combination(e, i) { 
 
    return [x_and_width_values[i], colors[i]]; 
 
    } 
 

 
//*******************acutal beef og code*************** 
 
var x_and_width_values=[]; 
 
//this link is needed to creation of svg elements 
 
var link="http://www.w3.org/2000/svg" 
 
//all your widths 
 
var all_widths=[224,84,29,3]; 
 
//all your colors 
 
var colors=['green','blue','darkgray','#606060']; 
 
//sort your width array to be on the safe side 
 
all_widths.sort(function(a,b){return b-a}); 
 
//find all width and x combination 
 
all_widths.reduce(combinations); 
 
//map width and x values to color values 
 
var all = x_and_width_values.map(colors_with_combination); 
 
//create a loop for object creation 
 
for(var i=0;i<all.length;++i){ 
 
var rect=document.createElementNS(link,'rect'); 
 
rect.setAttributeNS(null,'x',all[i][0][1]) 
 
rect.setAttributeNS(null,'width',all[i][0][0]); 
 
rect.setAttributeNS(null,'fill',all[i][1]); 
 
rect.setAttributeNS(null,'height','30'); 
 
rect.setAttributeNS(null,'y','0'); 
 
document.getElementById('svg').appendChild(rect);; 
 
}
<svg id='svg' width = '500' height= '100'> 
 
</svg>