Home > Net >  d3.js y-axis not displaying months correctly
d3.js y-axis not displaying months correctly

Time:01-01

I'm simply trying to create a y-axis labelled from January to December, but I can't understand why my code creates: January, March, March, April.... December. Can anyone explain this to me please? Thanks!

const w = 1078;
const h = 666;
const padding = 70;

const svg = d3
  .select("#svg-container")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

const months = Array(12)
  .fill(0)
  .map((v, i) => new Date().setMonth(i));

const yScale = d3
  .scaleTime()
  .domain([months[11], months[0]])
  .range([h - padding, padding]);

const yAxis = d3
  .axisLeft(yScale)
  .tickValues(months)
  .tickFormat(d3.timeFormat("%B"));

svg
  .append("g")
  .attr("transform", "translate("   padding   ", -20)")
  .attr("id", "y-axis")
  .call(yAxis);
body {
  background: gray;
}

svg {
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>

CodePudding user response:

That happens because setMonth() also sets the day you are currently in. Today is day 30 and February 2021 has only 28 days, therefore the non-existing February 30 2021 is in fact March 2 2021. You can see this if you print the dates in a different format:

enter image description here

To fix this, you can use the full Date function new Date(2021, i, 1)

const w = 1078;
const h = 666;
const padding = 70;

const svg = d3
  .select("#svg-container")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

const months = Array(12)
  .fill(0)
  .map((v, i) => new Date(2021, i, 1));

const yScale = d3
  .scaleTime()
  .domain([months[11], months[0]])
  .range([h - padding, padding]);

const yAxis = d3
  .axisLeft(yScale)
  .tickValues(months)
  .tickFormat(d3.timeFormat("%B %d"));

svg
  .append("g")
  .attr("transform", "translate("   padding   ", -20)")
  .attr("id", "y-axis")
  .call(yAxis);
body {
  background: gray;
}

svg {
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>

Good for you for posting this on the 30th, otherwise there would be a hidden bug waiting to appear!

Additional resources

MBostock's month axis example: https://bl.ocks.org/mbostock/1849162

D3 Scaletime documentation: https://observablehq.com/@d3/d3-scaletime

  • Related