Use D3.js for Data Visualisation with Rails

1. Install D3.js with gemfile

We will use gem “d3-rails” (see https://github.com/iblue/d3-rails) in this project. Add this line to your Gemfile:

gem "d3-rails"

D3.js will be provided via the asset pipeline and you don’t need to copy their files into your application. Rails will get them from d3-rails automatically. Then add it to your manifest file at app/assets/javascripts/application.js:

//= require d3

2. Customise rails assets pipeline for “data folder” in assets folder

Usually we only store images, JavaScripts and CSS in “Assets folder”. To store “data” in assets, we have to add this line in “application.rb” to customize the assets pipeline.

 config.assets.paths << Rails.root.join(“data”)

3. Basic concept of D3.js

D3.js is a library to bind datas and DOMs. There are three basic stages for our data.
1. Enter: Import the data which will create DOMs later.
2. Update: Update the data and change DOMs.
3. Exit: Remove DOMs when less data is shown after update.

Generally speaking, a common pattern is to break the initial selection into three parts: the updating nodes to modify, the entering nodes to add, and the exiting nodes to remove. In most cases, if you don’t remove unnecessary DOMs, performance will be increasingly poor.

4. Draw with SVG

  1. SVG area
  2. scale
  3. Import data
  4. coerce to number
<body>
<h1>D3 TEST</h1>
<div id=”line-chart”></div>
<style>
.chart {
border: 1px solid red;
}
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<svg class=”chart”></svg>
<script>
// Data
// var data = [4, 8, 15, 16, 23, 42];
var width = 420,
barHeight = 20;
// Set the scale
var x = d3.scale.linear()
// .domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(“.chart”)
.attr(“width”, width);
d3.tsv(“<%= asset_path ‘example_data.tsv’ %>”, type, function(error, data) {
x.domain([0, d3.max(data, function(d) { return d.value; })]);
chart.attr(“height”, barHeight * data.length);
var bar = chart.selectAll(“g”)
.data(data)
.enter().append(“g”)
.attr(“transform”, function(d, i) { return “translate(0,” + i * barHeight + “)”; });
bar.append(“rect”)
.attr(“width”, function(d) { return x(d.value); })
.attr(“height”, barHeight — 1);
bar.append(“text”)
.attr(“x”, function(d) { return x(d.value) — 3; })
.attr(“y”, barHeight / 2)
.attr(“dy”, “.35em”)
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value; // coerce to number
return d;
}
</script>