Jonathan Dunne
Jonathan Dunne

Reputation: 189

d3v4 How can i set a bar chart to distinct colours

I am looking to create a bar chart that uses multiple colours in a single chart. As i am using v4 I was looking to use d3.scaleBand().range, however this does not appear to be working, I have 7 distinct bars and i want to label all but the last in grey. the last one should be in a blue/teal colour.

If there was a way to do this within the style.css that would be great however if the solution can only be done within the main.js that would be fine too.

main.js

var margin = { left:80, right:20, top:50, bottom:100 };

var width = 600 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

var g = d3.select("#chart-area")
    .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
    .append("g")
        .attr("transform", "translate(" + margin.left + ", " + margin.top + ")");

// Define colour pallet
var color = d3.scaleBand().range(["#aeb3b7", "#aeb3b7", "#aeb3b7", "#aeb3b7",
                "#aeb3b7", "#3a6587", "#3a6587"]);

// X Label
g.append("text")
    .attr("y", height + 50)
    .attr("x", width / 2)
    .attr("font-size", "20px")
    .attr("text-anchor", "middle")
    .attr("fill", "#aeb3b7")  // This changes the Label text attr() or style()
    .text("Month");

// Y Label
g.append("text")
    .attr("y", -60)
    .attr("x", -(height / 2))
    .attr("font-size", "20px")
    .attr("text-anchor", "middle")
    .attr("transform", "rotate(-90)")
    .attr("fill", "#aeb3b7")  // This changes the Label text attr() or style()
    .text("Revenue");

d3.json("data/revenues.json").then(function(data){
    // console.log(data);


    // Clean data
    data.forEach(function(d) {
        d.revenue = +d.revenue;
    });

    // X Scale
    var x = d3.scaleBand()
        .domain(data.map(function(d){ return d.month }))
        .range([0, width])
        .padding(0.2);

    // Y Scale
    var y = d3.scaleLinear()
        .domain([0, d3.max(data, function(d) { return d.revenue })])
        .range([height, 0]);

    // X Axis
    var xAxisCall = d3.axisBottom(x);
    g.append("g")
        .attr("class", "axisEx")
        .attr("transform", "translate(0," + height +")")
        .call(xAxisCall);

    // Y Axis
    var yAxisCall = d3.axisLeft(y)
        .tickFormat(function(d){ return "$" + d; });
    g.append("g")
        .attr("class", "axisWhy")
        .call(yAxisCall);



    // Bars
    var rects = g.selectAll("rect")
        .data(data)

    rects.enter()
        .append("rect")
            .attr("y", function(d){ return y(d.revenue); })
            .attr("x", function(d){ return x(d.month) })
            .attr("height", function(d){ return height - y(d.revenue); })
            .attr("width", x.bandwidth)
            .attr("fill", function(d, i) {
                return color(i);
            })
            //.attr("fill", "#3a6587"); // This changes the column colour to a distinct colour
})

index.html

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <title>Star Break Coffee</title>
    <!-- Bootstrap -->
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <!-- Custom styling -->
    <link rel="stylesheet" href="css/style.css">
</head>

<body>

    <nav class="navbar navbar-default">
        <div class="container">
            <a class="navbar-brand" href="#"><img id="logo" src="img/logo.png"></a>      
        </div>
    </nav>

    <!-- Bootstrap grid setup -->
    <div class="container">
        <div class="row">
            <div id="chart-area"></div>
        </div>
    </div>

<!-- External JS libraries -->
<script src="js/d3.min.js"></script>
<!-- Custom JS -->
<script src="js/main.js"></script>

</body>
</html>

style.css

#chart-area svg {
    margin-left: auto;
    margin-right: auto;
    display: block;
}

#logo {
    height:50px;
}

.navbar-brand {
    height: 60px;
    padding: 5px 0px;
}

/*  Line is used to set the vertical 
portion of the graph should be grey 
to improve legibility */

.axisWhy line{
  stroke:  #aeb3b7; 
}

/*  path is used to set the axis ticks 
should be grey to improve legibility */

.axisWhy path{
  stroke: #aeb3b7;
}

/*  path is used to set the axis text 
should be black to contrast grey axis 
text */

.axisWhy text{
  fill: black;
} 


/*  Line is used to set the vertical 
portion of the graph should be grey 
to improve legibility */

.axisEx line{
  stroke:  #aeb3b7; 
}

/*  path is used to set the axis ticks 
should be grey to improve legibility */

.axisEx path{
  stroke: #aeb3b7;
}

/*  path is used to set the axis text 
should be black to contrast grey axis 
text */

.axisEx text{
  fill: black;
} 

/* Can be used to set the fill colour 
for a bar chart, however the colour is
used for all bars 
    rect {
    fill: #3a6587;
}
*/

revenues.json

[
    {
        "month": "January",
        "revenue": "13432",
        "profit": "8342"
    },
    {
        "month": "February",
        "revenue": "19342",
        "profit": "10342"
    },
    {
        "month": "March",
        "revenue": "17443",
        "profit": "15423"
    },
    {
        "month": "April",
        "revenue": "26342",
        "profit": "18432"
    },
    {
        "month": "May",
        "revenue": "34213",
        "profit": "29434"
    },
    {
        "month": "June",
        "revenue": "50321",
        "profit": "45343"
    },
    {
        "month": "July",
        "revenue": "54273",
        "profit": "47452"
    }
]

Thanks Jonathan

Upvotes: 0

Views: 154

Answers (1)

ofey
ofey

Reputation: 3327

All you need is,

var color = ["#aeb3b7", "#aeb3b7", "#aeb3b7", "#aeb3b7",
                    "#aeb3b7", "#3a6587", "#3a6587"];

and then,

.attr("fill", function(d, i) {
                return color[i];
            })

Upvotes: 1

Related Questions