Skip to content

Instantly share code, notes, and snippets.

@milroc
Forked from mbostock/.block
Last active October 23, 2019 20:09
Show Gist options
  • Save milroc/3056952 to your computer and use it in GitHub Desktop.
Save milroc/3056952 to your computer and use it in GitHub Desktop.
Minimum Viable Chart Junk (Updating Line Chart)

This is a fork of Mike Bostock's Line Transition.

This fork was originally intended to showcase a principle of using padding between the x and y axis. This is a concept I've seen covered over and over again when dealing with non-zero minimum value charts (see example).

I also found it interesting to update both the line and the x axis. It should be noted that this was not the intent of the line transition example, seeing that the line was treated as a queue, pushing and popping from the front and back of the data. It talked on how to prevent odd visual behavior of the path when those changes occur, nothing more or less.

That being said, the visual change to the axis was a hack (see x_axis_scale) to just better understand how useful a constant, fast linear change effects my comprehension of the data.

So far, my personal opinion is that when dealing with updating data similar to this, it is best to spend most of your non-data visual queues to aid in comprehending the changing axis. It seems hard to distinguish between a major point (e.g any multiple of 5) and the points to it's immediate right and left, by extending the tick size of the x axis, you add more "chart junk" but help aid yourself (or your user) in comprehending the data.

I believe that this example is one of the charts that has near to bare minimum "chart junk" while still allowing the user to easily understand the data.

If you have thoughts, or have forked this gist to offer different changes, contact me on twitter: @milr0c.

TODO: Combine both transitions into one, to prevent odd pausing behavior of x-axis (might be my eyes playing tricks on me).

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background-color: #3E4651;
}
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: #FFF;
stroke-width: 1.5px;
}
.axis line, .axis path {
stroke: #FFF;
opacity: .1;
shape-rendering: crispEdges;
fill: none;
}
.axis path {
display: none;
}
.axis text {
fill: #FFF;
}
}
</style>
<body>
<script src="http://mbostock.github.com/d3/d3.js?2.7.2"></script>
<script>
var n = 40,
random = d3.random.normal(4, .2),
data = d3.range(n).map(random),
i = 0;
var margin = {top: 10, right: 10, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var axis_padding = 30;
var x = d3.scale.linear()
.domain([0, n - 1])
.range([0, width]);
var x_axis_scale = d3.scale.linear()
.domain([i, n - 1])
.range([0, width]);
var y = d3.scale.linear()
.domain([3, 5])
.range([height - axis_padding, 0]);
var line = d3.svg.line()
.x(function(d, i) { return x(i); })
.y(function(d, i) { return y(d); });
var svg = d3.select("body").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 + ")");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var x_axis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom").tickSize(-height));
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
tick();
function tick() {
// push a new data point onto the back
i++;
data.push(random());
x_axis_scale = d3.scale.linear()
.domain([i, n - 1 + i])
.range([0, width]);
x_axis.transition().duration(500).ease("linear").call(d3.svg.axis().scale(x_axis_scale).orient("bottom").tickSize(-height));//.each("end", tick);
// redraw the line, and slide it to the left
path
.attr("d", line)
.attr("transform", null)
.transition()
.duration(500)
.ease("linear")
.attr("transform", "translate(" + x(-1) + ")").each("end", tick);
// pop the old data point off the front
data.shift();
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment