Search code examples
javascriptd3.jsgraphcolorscolor-picker

D3: Bar chart coloring


I have a bar chart with x and y values in D3 and I want to color my bars depending on the value of y. If y is smaller then 6 then it should be one color and if otherwise I want another color for it.

This is my code so far. This is working just for one value.

var data = [
                                            {x: 2, y:  4},
                                            {x: 5, y:  8},
                                            {x: 8, y: 10}
                                        ];

  bars.selectAll(".rect")
                                            .data(data)
                                            .enter().append("rect")
                                            .attr("class", "rect")
                                            .attr("x", function(d) { return x(d.x); })
                                            .attr("y", function(d) { return y(d.y); })
                                            .attr("height", function(d) { return h - y(d.y); })
                                            .attr("width", 15)
                                            .attr("fill", function(d){
                                                return colorPicker(d);
                                            });

                                        function colorPicker(v){
                                            if(v<=6) { return "#666666"}
                                            else if (v > 6){ return "#FF0033";}

                                        }

Do you have any idea how should I change this ? Thanks in advance!


Solution

  • The simplest way for setting the colour according to that rule is using a ternary operator:

    .attr("fill", function(d){ return d.y > 6 ? "#FF0033" : "#666666"});
    

    Check the demo:

    var w = 300, h = 100, padding = 20;
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);
    
    var data = [{name: "foo", y:10},
                {name: "bar", y:30},
                {name: "baz", y: 5}];
    
    var xScale = d3.scaleBand()
      .range([0,w])
      .domain(data.map(function(d){ return d.name}))
      .paddingInner(0.2)
      .paddingOuter(0.2);
    
    var yScale = d3.scaleLinear()
      .range([h - padding, 0])
      .domain([0, d3.max(data, function(d){ return d.y})]);
    
    var xAxis = d3.axisBottom(xScale);
    
    var bars = svg.selectAll(".bars")
      .data(data)
      .enter()
      .append("rect");
    
    bars.attr("x", function(d){ return xScale(d.name)})
      .attr("width", xScale.bandwidth())
      .attr("y", function(d){ return yScale(d.y)})
      .attr("height", function(d){ return h - padding - yScale(d.y)})
      .attr("fill", function(d){ return d.y > 6 ? "#FF0033" : "#666666"});
    
    var gX = svg.append("g")
      .attr("transform", "translate(0," + (h - padding) + ")")
      .call(xAxis);
    <script src="https://d3js.org/d3.v4.min.js"></script>

    However, if you want to keep that function, you have to call colorPicker using d.y as an argument, not d:

    colorPicker(d.y)
    

    Check the demo:

    var w = 300, h = 100, padding = 20;
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);
    
    var data = [{name: "foo", y:10},
                {name: "bar", y:30},
                {name: "baz", y: 5}];
    
    var xScale = d3.scaleBand()
      .range([0,w])
      .domain(data.map(function(d){ return d.name}))
      .paddingInner(0.2)
      .paddingOuter(0.2);
    
    var yScale = d3.scaleLinear()
      .range([h - padding, 0])
      .domain([0, d3.max(data, function(d){ return d.y})]);
    
    var xAxis = d3.axisBottom(xScale);
    
    var bars = svg.selectAll(".bars")
      .data(data)
      .enter()
      .append("rect");
    
    bars.attr("x", function(d){ return xScale(d.name)})
      .attr("width", xScale.bandwidth())
      .attr("y", function(d){ return yScale(d.y)})
      .attr("height", function(d){ return h - padding - yScale(d.y)})
      .attr("fill", function(d){return colorPicker(d.y);});
    
    function colorPicker(v){
     if(v<6) { return "#666666"}
     else{ return "#FF0033";}}
    
    var gX = svg.append("g")
      .attr("transform", "translate(0," + (h - padding) + ")")
      .call(xAxis);
    <script src="https://d3js.org/d3.v4.min.js"></script>