Designing Responsive Charts Using D3JS

Introduction

This article is all about how easy it is to make your charts responsive by making a few changes in your code. So this article is all about how to make your chart more user-friendly using a few cool effects.

Outlines

  • Overview
  • Responsiveness
    • Zoom Effect
    • Scroll Effect
  • Demo
    • HTML Snippet
    • JavaScript Snippet
    • CSS Snippet
    • Output
      • Zoom Effect
      • Scroll Effect
  • Summary

Overview

I hope you guys already have some feel of D3.JS and it's respective functionality based on my previous article. This article is one more step in that series. So by reading the core of this article, you will have some ideas in your mind about this article.

So this article explains how easily and effectively you can make your charts responsive and interactive using certain lines of codes (in JavaScript). Let's see what you will learn in this article.

Responsiveness | Explanation

I guess all of you must be familiar with "responsive or responsiveness" that simply means how to make our things more and more user-friendly.

For making my charts a bit responsive I am using these 2 effects.

Responsiveness

Zoom Effect

In the Zoom effect if you click the output then the chart will be magnified. You can do that function up to a limit and power of being Zoomed repetitively directly proportional to the number of dependent clicks.

Defining Attributes.

// Calling Chart Attributes and Behaviour  
var chart = d3.select(location).append("svg")  
    .attr("class", "chart")  
    .attr("width", graph_width + 20)  
    .attr("height", graph_height + 20)  
    .call(d3.behavior.zoom()
        .x(x)
        .scaleExtent([1, 8])
        .on("zoom", zoom));

Here is a Zoom function that will create a Zoom effect for us.

function zoom() {  
    chart.select(".xaxis").call(xAxis);  
    chart.select(".yaxis").call(yAxis);  
    chart.selectAll(".chart rect")
        .attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}

You will see the functioning of that effect later in this article in the Output portion. Until then check out the scroll effect.

Scroll Effect

From the scroll effect I mean, you can scroll your chart along any axis by simply holding the background through your mouse cursor. In this article's code snippet, there is only an X-axis (left and right-hand scrolling) effect.

But you can make it along the y-axis too.

Demo


HTML Snippet

Just write a simple HTML snippet and embed JavaScript and CSS code snippets in it. Don't forget to provide this tag line.

<div id="post"></div>

JavaScript Snippet

Here is the JavaScript snippet that will generate a Column chart, or I better say a Responsive (Zooming Effect chart) Chart with it. For that, I am using a simple JavaScript structure like code snippet and D3.JS functionality in it along with JSON data.

// JSON Data
var data = [
    { "date": "2012-01-01", "num": 5 },
    { "date": "2012-01-05", "num": 10 },
    { "date": "2012-01-10", "num": 22 },
    { "date": "2012-01-15", "num": 72 },
    { "date": "2012-01-20", "num": 87 },
    { "date": "2012-01-21", "num": 90 }
];
// Function for Creating the Required Chart
function draw() {
    // Providing Required Parameters
    var location = "#post";
    var month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    var graph_width = 500;
    var graph_height = 200;
    // Declaring Some Functionality-Oriented Parameters
    var values = _.pluck(data, 'num');
    var max_val = d3.max(values);
    var v_scale = graph_height / max_val;
    var data_counts = data.length;
    var bar_width = graph_width / data_counts;
    var minDate = new Date(data[0]["date"]);
    var maxDate = new Date(data[data.length - 1]["date"]);
    // Defining Range of a Graph
    var y = d3.scale.linear()
        .domain([0, max_val])
        .range([graph_height, 0]);
    console.log(minDate);
    var x = d3.time.scale()
        .domain([minDate, maxDate])
        .range([0, graph_width]);
    // Calling Chart Attributes and Behaviour
    var chart = d3.select(location).append("svg")
        .attr("class", "chart")
        .attr("width", graph_width + 20)
        .attr("height", graph_height + 20)
        .call(d3.behavior.zoom()
            .x(x)
            .scaleExtent([1, 8])
            .on("zoom", zoom));
    var lines = chart.selectAll("line");
    // Functionality for Y Axis
    var lines_y = lines
        .data(x.ticks(5))
        .enter().append("line")
        .attr("x1", x)
        .attr("x2", x)
        .attr("y1", function (d) {
            return graph_height - 20 - d;
        })
        .attr("y2", graph_height)
        .style("stroke", "#ccc");
    // Functionality for X Axis
    var lines_x = lines
        .data(y.ticks(10))
        .enter().append("line")
        .attr("x1", 0)
        .attr("x2", graph_width)
        .attr("y1", y)
        .attr("y2", y)
        .style("stroke", "#ccc");
    // Scaling of Chart for Both Axes
    var xAxis = d3.svg.axis().scale(x);
    var yAxis = d3.svg.axis().scale(y).orient("left");
    chart.append("svg:g")
        .attr("class", "xaxis")
        .attr("transform", "translate(0,200)")
        .call(xAxis);
    chart.append("svg:g")
        .attr("class", "yaxis")
        .attr("transform", "translate(25,0)")
        .call(yAxis);
    var rect = chart.selectAll("rect")
        .data(data).enter()
        .append("rect")
        .attr("x", function (d, i) { return x(new Date(d["date"])) + 20; })
        .attr("y", function (d, i) { return graph_height - (d["num"] * v_scale); })
        .attr("width", x(new Date(data[1]["date"])))
        .attr("height", function (d, i) { return d["num"] * v_scale; });
    // Calling ZOOM Function for Some Responsive Effects
    function zoom() {
        chart.select(".xaxis").call(xAxis);
        chart.select(".yaxis").call(yAxis);
        chart.selectAll(".chart rect")
            .attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
    }
}
draw();

CSS Snippet

Here's our simple CSS snippet.

div#post {
    width: 500px;
    height: 210px;
}
.chart rect {
    stroke: white;
    fill: steelblue;
}

Output

This is the real output you will get through that code snippet.

Scroll Effect

Output | Zoom Effect

+2 Zoom Effect

First of all I will you why I am calling it responsive. First of all, I'll show you the Zoom effect.

If you double-click on the preceding output then you will get a normal Zoom effect, that is shown in the following image.

Normal Zoom Effect

+3 Zoom Effect

For the sake of being responsive, if you click thrice then you will get something like that in your browser (More Zoom effect, extra wide bars).

More zoom Effect

+5 Zoom Effect

Now, if you want an increasingly magnified chart then continue to click (maybe 5 to 7 times) and then you will get something like that.

Extra Zoom Effect

For more and more effects try clicking.

Output | Scrolling Effect

Now I will show you the scrolling responsiveness of this graph. You can do this on the right and left-hand side-scrolling.

Right Side-Scrolling Effect

For that effect if you hold the background and swap the cursor to the right then you will get your chart something like the following (Right Scrolling Effect).

Right Side Scroll Effect

Left Side-Scrolling Effect

For that effect if you hold the background and swap the cursor to the left then you will get your chart something like the following.

Left Side Scroll Effect

Summary

I hope you have enjoyed this article and learned something. That was my original intent. Keep in touch for more informative and interesting technology terms.

Meanwhile, if you have any queries, then feel free to ask.

#HappyCoding!