Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show every other tick label on d3 time axis?

I've got a d3 chart with an x-axis that uses a custom time format:

var x = d3.time.scale.utc()
        .domain([start, end])
        .range([0, width]);

var customTimeFormat = d3.time.format.utc.multi([
    ["%b %d", function(d) { return d.getUTCDate() != 1; }],
    ["%b", function(d) { return d.getUTCMonth(); }],
    ["%Y", function() { return true; }]
]);

var xAxisTop = d3.svg.axis()
                .scale(x)
                .orient("top")
                .tickFormat(customTimeFormat)
                .innerTickSize(-height)
                .outerTickSize(0)
                .ticks(d3.time.month.utc, 1);

What I'd like to be able to do is to have a tick for each month, but only a label for each third month. All I seem to be able to do, however, is to either (a) have a tick and label for each month or (b) have a tick and label for every third month.

How can I specify to draw ticks every month, but only have the labels show up for every third month?

like image 215
Jonah Bishop Avatar asked Aug 12 '16 15:08

Jonah Bishop


2 Answers

I think tickformats are really helpful here to keep it clean, atleast worked for me.

code is untested but i just want to draw attention to how we can manipulate tickformat.

var xAxisTop = d3.svg.axis()
                .scale(x)
                .orient("top")
                .tickFormat((interval,i) => {
                  return i%3 !== 0 ? " ": interval;
                 })
                .innerTickSize(-height)
                .outerTickSize(0)
                .ticks(d3.time.month.utc, 1);
like image 80
hafiz ali Avatar answered Nov 02 '22 17:11

hafiz ali


You can do that regardless your x axis using a custom time format.

One solution is simply finding the text in that tick and removing it:

var ticks = d3.selectAll(".tick text");
ticks.each(function(_,i){
    if(i%3 !== 0) d3.select(this).remove();
});

I'm using the modulo (i%3) to get the multiples of 3. You can use any other number you want.

Here is a demo:

var width = 550,
  height = 200;

var data = [{
    month: "Jan"
  },
  {
    month: "Feb"
  },
  {
    month: "Mar"
  },
  {
    month: "Apr"
  },
  {
    month: "May"
  },
  {
    month: "Jun"
  },
  {
    month: "Jul"
  },
  {
    month: "Aug"
  },
  {
    month: "Sep"
  },
  {
    month: "Oct"
  },
  {
    month: "Nov"
  },
  {
    month: "Dec"
  },
];

var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var xScale = d3.scaleBand()
  .domain(data.map(function(d) {
    return d.month
  }))
  .range([0, width * 0.95])

var xAxis = d3.axisBottom(xScale);

svg.append("g")
  .attr("transform", "translate(10,100)")
  .attr("class", "x axis")
  .call(xAxis);

var ticks = d3.selectAll(".tick text");

ticks.each(function(_, i) {
  if (i % 3 != 0) d3.select(this).remove();
});
.axis path,
.axis line {
  fill: none;
  stroke: #4e5a64;
  shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
like image 28
Gerardo Furtado Avatar answered Nov 02 '22 16:11

Gerardo Furtado