Reputation: 139
I have a stacked bar chart in d3. Each stack is made up of 4 svg rectangles. I would like to create a text box above each stack in the chart with a stack total.
The last rectangle in the stack data[i][3] contains elements x, y and y0. i represents stacks 0 through 3.
Here's a console output for :
.data(data.filter(function(d,i){
console.log("This is i: " + i);
console.dir(d[3]);
return d[3];
}))
This is i: 0 x: 0 y: 0.46 y0: 2.4
The idea is that I will be able to create a dataset for just the last rectangle of each stack and then find the y position for the text box by adding y and y0 for that rectangle.
I am able to do this using the d3 .filter(":last-child") option, but it creates empty rect elements which I do not want. When I try a javaScript filter I get a NaN result for d.x and d.y values. Any advice?
stack.selectAll('.stackTotalBox')
.data(data.filter(function(d,i){
console.log("This is i: " + i);
console.dir(d[3]);
return d[3];
}))
.enter()
.append("rect")
// .filter(":last-child") -- this works but generates empty rect
.attr("class","stackTotalBox")
.attr("x", function (d) {
console.dir(d);
return xScale(d.x) + 170/2 - 39.12; // + width of stack/2 - width of text box/2
})
.attr("y", function (d) {
return yScale(d.y0 + d.y) - 40; // height of stack + room for text box
})
.attr("width", 78.24) // width of text box
.attr("height", 19.347) // height of text box
.attr("rx", 8) // rounded corners
.attr("ry", 8) // rounded corners
.attr("fill", "#BBBDBF");
Update with data structure of data
Data contains 4 arrays (one array per stack), each array has 4 objects(rectangles), Each object contains coordinates for a rectangle.
This is how it looks in console with the first stack/array expanded:
Array[4]
--> 0: Array[4] (This represents a Stacked bar)
----> 0: Object
----> 1: Object
----> 2: Object
----> 3: Object (This Represents the last rectangle in the stacked bar)
--------> x: 0 (First Array has x = 0, 2nd Array x = 1)
--------> y: 0.4 (height of rectangle)
--------> y0: 2.13 (height of preceding rectangles, starting Y coordinates)
--> 1: Array[4]
--> 2: Array[4]
--> 3: Array[4]
Upvotes: 0
Views: 417
Reputation: 742
I see. You should use Array.prototype.map
instead of Array.prototype.filter
. if you use filter
then your output will be included whenever closure return true
.
So in your case, since d[3]
is an object and it's always true, you basically didn't filter anything and thus d
is still a 2-d array, and d.x
is undefined.
Try this to filter your data:
stack.selectAll('.stackTotalBox')
.data(data.map(function(item){
return item[3];
}))
Upvotes: 1