I'm building a bar plot in d3.js in which each bar represents total TB cases during a month. The data essentially consists of a date (initially strings in %Y-%m format, but parsed using d3.time.format.parse) and an integer. I'd like the axis labels to be relatively flexible (show just year boundaries, label each month, etc.), but I'd also like the bars to be evenly spaced.
I can get flexible axis labeling when I use a date scale:
var xScaleDate = d3.time.scale() .domain(d3.extent(thisstat, function(d) { return d.date; })) .range([0, width - margin.left - margin.right]);
... but the bars aren't evenly spaced due to varying numbers of days in each month (e.g., February and March are noticeably closer together than other months). I can get evenly-spaced bars using a linear scale:
var xScaleLinear = d3.scale.linear() .domain([0, thisstat.length]) .range([0, width - margin.left - margin.right]);
... but I can't figure out how to then have date-based axis labels. I've tried using both scales simultaneously and only generating an axis from the xScaleDate
, just to see what would happen, but the scales naturally don't align quite right.
Is there a straightforward way to achieve this that I'm missing?
You can combine ordinal and time scales:
// Use this to draw x axis var xScaleDate = d3.time.scale() .domain(d3.extent(thisstat, function(d) { return d.date; })) .range([0, width - margin.left - margin.right]); // Add an ordinal scale var ordinalXScale = d3.scale.ordinal() .domain(d3.map(thisstat, function(d) { return d.date; })) .rangeBands([0, width], 0.4, 0); // Now you can use both of them to space columns evenly: columnGroup.enter() .append("rect") .attr("class", "column") .attr("width", ordinalXScale.rangeBand()) .attr("height", function (d) { return height - yScale(d.value); }) .attr("x", function (d) { return xScaleDate(d.date); }) .attr("y", function (d){ return yScale(d.value); });
I've created an example a while ago to demonstrate this approach: http://codepen.io/coquin/pen/BNpQoO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With