I'm trying to get d3 to draw a single stacked bar chart, like so:
<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>
As you can see, the x position starts at zero, then each subsequent x position is equal to the sum of the preceding widths.
So I'm trying to get d3 to draw something like that from an array called datavars:
var datavars = [224, 84, 29, 3];
... and to ensure that d3 assigns the correct width-value to the correct x-value, I created these variables:
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];
... and define the x value like so:
//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);
As you might have guessed, the strongly-indented function (based on the sum of the preceding widths, and defined in the prev_width
variables) returns a string for each iteration (prev_width0, prev_width1, etc.) and not the values I thought I defined when I created the prev_width
variables.
I'm obviously defining the variables incorrectly. Any idea how I can do this properly?
JavaScript does not interpret the string "datavars1"
as the variable datavars1
. To interpret a string as a JavaScript variable you can use eval()
. So change: return 'prev_width'+i; })
to return eval('prev_width'+i); })
. Although a better idea might be to use an array instead such as:
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
You can do a similar thing with the colors:
var colors = ['green','blue','darkgray','#606060'];
...
.attr('fill', function(d, i){ return colors[i]; })
Bar chart with color
You can also create a single array of objects to store the color, width, etc.
A more scalable idea would be to get rid of the array prev_width
and have a function that can take the sum up to a point. Such as:
function sum(array, start, end) {
var total = 0;
for(var i=start; i<end; i++) total += array[i];
return total;
}
Then you can do:
...
.attr('x',function(d, i){
return sum(datavars, 0, i); })
Example using summation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With