Ed G
Ed G

Reputation: 101

d3.timeDay.every(step) resets each month, causing colliding axis labels

I am creating a chart that has daily data for some number of sequential days. Each object in the data array has a date property, which is that day's JavaScript Date representation at midnight. Here is the relevant code:

  const x = d3.scaleTime()
    .range([0, width])
    .domain(d3.extent(data.map(d => d.date)));

  const days = data.length;
  let interval = 1;
  while (width / (days - 1) * interval < 60) {
    interval += 1;
  }

  const xAxis = d3.axisBottom(x)
    .tickFormat(d3.timeFormat('%b %d'))
    .ticks(d3.timeDay.every(interval));

The problem is that d3.timeDay.every(interval) resets at the start of each month. The d3 docs clearly point this out, so it is not a bug.

Unfortunately, it leads to ticks and labels that are too close together when dates cross month boundaries.

Is there a way to make the X axis (which is a scaleTime) create ticks every interval days regardless of month boundaries?

Upvotes: 2

Views: 2928

Answers (1)

Ed G
Ed G

Reputation: 101

OK, asking the question made me focus. I found an answer. I needed to provide my own tick values. This worked:

  const xValues = data.filter((d, i) => i % interval === 0).map(d => d.date);

  const xAxis = d3.axisBottom(x)
    .tickFormat(d3.timeFormat('%b %d'))
    // .ticks(d3.timeDay.every(interval))
    .tickValues(xValues);

I am beginner with d3 and would welcome a better answer.

Upvotes: 4

Related Questions