Shawn Shawn - 2 months ago 17
Javascript Question

d3js: adding multiple colors to each bars based on variables using if condition

I created a horizontal bar chart.

The width of each bar is based on object variable volume. Later I realized I need to make each bar a stack bar instead, the 2 categories object variables are vol1 & vol2, where vol1 + vol2 = volume.

I was wondering if there is a direct way to assign 2 colors to each bar based on vol1 & vol2 values instead of the usual stacked bar method where you need to (a) arrange data in arrays based on their categories, (b) define x, y, y0 (c) assign different colors to each array bars.

data structure:

var data = [
{ "merchant": "A",
"volume": 100,
"vol1": 48,
"vol2": 52
},
{...},
{...}
];


The specific code to draw the chart is:

var bar = d3.select(".mainGroup").selectAll(".bar")
.data(data_merchantTop100Vol);

bar.attr("x", 0)
.attr("y", d => y(d.merchant))
.attr("height", y.rangeBand())
.transition().duration(50)
.attr("width", d => x(d.volume));

bar.enter().append("rect")
.attr("class", "bar")
.attr("x", 0)
.attr("y", d => y(d.merchant))
.attr("height", y.rangeBand())
.transition().duration(50)
.attr("width", d => x(d.volume))
// THIS PART IS TO FILL 2 COLORS TO THE 2 SECTIONS OF EACH BAR
// .style("fill", function(d) {
// if(d.Vol1) { return "blue"}
// else if (d.vol2) { return "red"};
// })


In short, I want to create a horizontal stacked bar using if-condition coloring method instead of typical stacked bar method. Idea inspiration: http://www.d3noob.org/2013/01/select-items-with-if-statement-in-d3js.html

Current horizontal bar chart:

enter image description here

Desired outcome:

enter image description here

Answer

You could try to fill the rectangles with gradients using the right percentages but this would over complicate the solution. The easiest way would be using one rectangle for each color. You do not need to rearrange the data for this:

// Vol1 bars
    bar.enter().append("rect")
        .attr("class", "bar")
        .attr("x", 0)
        .attr("y", d => y(d.merchant))
        .attr("height", y.bandwidth())
        .transition().duration(50)
        .attr("width", d => x(d.vol1))
    .style("fill", "blue")

// Vol2 bars
    bar.enter().append("rect")
        .attr("class", "bar")
        .attr("x", d => x(d.vol1))
        .attr("y", d => y(d.merchant))
        .attr("height", y.bandwidth())
        .transition().duration(50)
        .attr("width", d => x(d.vol2))
    .style("fill", "red")