Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active January 13, 2017 19:31
Show Gist options
  • Save mbostock/4349486 to your computer and use it in GitHub Desktop.
Save mbostock/4349486 to your computer and use it in GitHub Desktop.
ggplot2-Style Axis
license: gpl-3.0

These axes are styled in the manner of ggplot2, a plotting system for R. Two d3.svg.axis instances are used: one for the gray grid lines, and one for the black ticks and labels below the bottom of the chart area. The exit selection of a data-join is used to customize the appearance of minor ticks.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
shape-rendering: crispEdges;
}
.grid-background {
fill: #ddd;
}
.grid line {
stroke: #fff;
}
.grid .minor line {
stroke-opacity: .5;
}
.grid text {
display: none;
}
.axis line {
stroke: #000;
}
.axis path,
.grid path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 200, right: 10, bottom: 200, left: 10},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([.05, .95])
.range([0, width]);
var y = d3.scale.linear()
.range([0, height]);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("class", "grid-background")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).ticks(20).tickSize(-height))
.selectAll(".tick")
.data(x.ticks(10), function(d) { return d; })
.exit()
.classed("minor", true);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).ticks(10));
</script>
@HamsterHuey
Copy link

Mike, while this works really well, it appears to me that this approach is not guaranteed to work since x.ticks(10) is not guaranteed to give you every alternate tick in x.ticks(20) due to some of the magic that happens in the background to produce sane ticks for axes. Is there an approach you'd recommend to get this right a 100% of the time? I tried this approach for a chart with zoom enabled, and minor grid stopped working correctly for certain zoom scales where x.ticks(10) did not provide half the number of ticks at same data points as x.ticks(20).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment