D3js group bar chart subgroups with 0 value - javascript

I'm trying to do something similar to this example but I'm passing a 0 value to one subgroup.
so I have a result like this.
is there a way to make one of the other subgroups have this blank space?, I thought it would be something like this.
svg.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) { return "translate(" + x(d.group) + ",0)"; })
.selectAll("rect")
.data(function(d) { return subgroups.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
///.attr("x", function(d) { return xSubgroup(d.key); })//change this line to the next one
.attr("x", function(d) { if (d.value>0){return xSubgroup(d.key); }})
.attr("y", function(d) { return y(d.value); })
.attr("width", xSubgroup.bandwidth())
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return color(d.key); });

Related

How to label each bar from a grouped bar chart?

I'm newbie with D3.js and I have created a grouped bar chart. And I would like to put the value at the top of echa bar. But, I'm not able to do it :(
I have found several solutiones but I cannot do it works fine.
You can find all the code of my development here:
The function where I create all the bars is:
setBars(canvas, data, scales, keys, colors) {
let height = HEIGHT - OFFSET_TOP - OFFSET_BOTTOM;
let bar = canvas
.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + scales.x0Scale(d.shoot) + ",0)";
})
.selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return { key: key, value: d[key] };
});
})
.enter()
.append("rect")
.attr("class", "rect")
.attr("x", function(d) {
return scales.x1Scale(d.key);
})
.attr("y", function(d) {
return scales.yScale(d.value);
})
.attr("width", scales.x1Scale.bandwidth())
.attr("height", function(d) {
return height - scales.yScale(d.value);
})
.attr("fill", function(d) {
return colors(d.key);
});
//set label over bar
bar
.selectAll("g")
.data(function(d) {
return d.value;
})
.enter()
.append("text")
.attr("class", "bar-text")
.attr("fill", "#000")
.attr("text-anchor", "middle")
.text(function(d) {
console.log("d.value: " + d.value);
return d.value;
})
.attr("x", function(d, i) {
return scales.x1Scale.bandwidth() * (i + 0.5);
})
.attr("y", function(d, i) {
return scales.yScale(d.value) + 8;
});
}
What am I doing wrong?
If you look at the chain in your bar selection you'll see that you're trying to append text elements to rects: bar is a selection of rectangles, not a selection of groups. Appending texts to rectangles, of course, won't work in an SVG.
The solution is breaking that selection. For instance:
//This is the group selection:
let bar = canvas
.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + scales.x0Scale(d.shoot) + ",0)";
});
//Here, you append rects to the groups:
bar.selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return {
key: key,
value: d[key]
};
});
})
.enter()
.append("rect")
//etc...
//Finally, here, you append texts to the groups:
bar.selectAll("text")
.data(function(d) {
return keys.map(function(key) {
return {
key: key,
value: d[key]
};
});
})
.enter()
.append("text")
//etc...
As you can see, you'll have to change the data() method as well.

d3js v5 Resize Grouped Bar Chart

I'm trying to resize a grouped bar chart with a resize() function.
function resize(){
width = parseInt(d3.select(".c_chart").style("width"), 10);
x0.rangeRound([margin.left, width-margin.right]);
x1.rangeRound([margin.left,x0.bandwidth()-margin.right])
yAxis.tickSize(width);
svg.selectAll("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("width", x1.bandwidth());
svg.selectAll(".x_axis")
.call(xAxis)
.selectAll("text")
.call(wrap, x0.bandwidth());
}
When I start to resize the window, x-axis is ok but the x-position of my recent don't "follow" the ticks of my x-axis.
Then, I suspect that the problem is due to x- attribute but how can I fix that?
Here is my code: https://plnkr.co/edit/XEoM7lsBvZQmY87Wz1SP?p=preview
Add a class (gbar) to the g containing the group
svg
.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.categorie) + ",0)"; })
.attr("class", "gbar")
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x1.bandwidth())
.attr("height", function(d) { return height-margin.bottom - y(d.value); })
.attr("fill", function(d) { return z(d.key); });
In the resize function update the translation
svg.selectAll(".gbar")
.attr("transform", function(d) { return "translate(" + x0(d.categorie) + ",0)"; });
and update the size of the SVG
svg
.attr("width",width)
.attr("height",height);
Don't take the margin in the x1 scale
const x1 = d3.scaleBand()
.padding(0.05)
.domain(keys)
//.rangeRound([margin.left,x0.bandwidth()-margin.right])
.rangeRound([0,x0.bandwidth()]);
// resize()
//x1.rangeRound([margin.left,x0.bandwidth()-margin.right])
x1.rangeRound([0,x0.bandwidth()])
The only thing left to fix is the y-axis grid line,........

How to update a grouped bar-chart in d3js

In this plunker I've attempted to update the bars based on new csv data in a similar fashion to this.
It fetches the new data and updates the rectangles but doesn't remove the previous data.
I have no idea what part of the code isn't working right, in a previous attempt I omitted .attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
and got the leftmost group of bars to update and remove previous data but none of the other groups were showing.
Appreciate any help!
EDIT: Uploaded a working example here
Here's the relevant code:
let bars = g.selectAll(".test")
.data(data)
bars = bars.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
.selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return {key: key, value: d[key]};
});
})
bars = bars
.enter().append("rect")
.attr("width", x1.bandwidth())
.attr("x", function(d) { return x1(d.key); })
.attr("fill", function(d) { return z(d.key); })
.merge(bars)
bars.transition()
.duration(750)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
bars.exit().remove();
The layers/groups in the chart do not seem to update as per the new data. Here's some changes you could make to the bars' enter, update and exit code:
var barGroups = g.selectAll("g.layer").data(data);
barGroups.enter().append("g").classed('layer', true)
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
barGroups.exit().remove();
var bars = g.selectAll("g.layer").selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return {key: key, value: d[key]};
});
});
bars.enter().append("rect").attr("width", x1.bandwidth())
.attr("x", function(d) { return x1(d.key); })
.attr("fill", function(d) { return z(d.key); })
.transition().duration(750)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
bars
.transition().duration(750)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
bars.exit().remove();
So if you look at the code, bar groups/layers are being dealt with first and then the actual bars i.e. rectangles. Let me know if this doesn't work.
Hope this helps. :)

Adding Label Text on Barchart D3js

I'm trying to figure out the correct way to displays labels that will sit on top of each bar in my bar chart. I'd also like them to display a % after the number.
Here is my Plunker: https://plnkr.co/edit/FbIquWxfLjcRTg7tiX4E?p=preview
I experimented with using this code from the question found in the link below. However, I wasnt able to get it to work properly (meaning the whole chart failed to display)
Adding label on a D3 bar chart
var yTextPadding = 20;
svg.selectAll(".bartext")
.data(data)
.enter()
.append("text")
.attr("class", "bartext")
.attr("text-anchor", "top")
.attr("fill", "white")
.attr("x", function(d,i) {
return x(i)+x.rangeBand()/2;
})
.attr("y", function(d,i) {
return height-y(d)+yTextPadding;
})
.text(function(d){
return d;
});
This is the most straight forward way given your existing code:
// keep a reference to the g holding the rects
var rectG = g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter();
// append the rects the same way as before
rectG.append("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x1.bandwidth())
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return z(d.key); });
// now add the text to the g
rectG.append("text")
.text(function(d){
return d.value + '%';
})
.attr("x", function(d) { return x1(d.key) + (x1.bandwidth()/2); })
.attr("y", function(d) { return y(d.value); })
.style("text-anchor", "middle");
Updated plunker.

Access x value on axis d3 stacked bar chart

1.
I think this is a simple question but I'm not getting it. I have the following code for the x-axis of my Stacked bar chart, and I'm trying to access the x-value when the corresponding stacked bar is clicked. I've tried selecting xAxis, x, and .domain, but I'm getting null values.
data = [
{State: "Greg", Achieved:10,Breached:10},
{State: "Ari", Achieved:10,Breached:10},
{State: "Loser", Achieved:10,Breached:10}
];
// From JSON object state represents X axis (I want to get this).
var state = vis.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.attr("width", x.rangeBand())
.on("click", function(d, i){ console.log(x.rangeBand());return scope.onClick({item: d});});

Categories

Resources