I have an SVG Element which want to be a line Graph. The xAxis of the graph should display years (best with 1 year intervalls: 1980, 1981, ...)
My dataset has year-values which I extract into a d3.extent variable which retruns the 2 year values I need as extent of my xAxis.
var timeExtent (2) [1980, 2019]
then I declare xScale:
let xScale = d3.scaleTime()
.domain(timeExtent)
.range([0, width]);
then I declare xAxis:
let x_axis = d3.axisBottom(xScale);
then I append my svg element with an xAxis:
lineGraph_svg.append("g")
.attr("class", "x axis")
.attr("transform", `translate(${margin},${height})`)
.call(x_axis.tickFormat(d3.timeFormat("%Y")))
.selectAll("text")
.style("text-anchor", "end")
.attr("transform", "rotate(-65)")
Now, the the xAxis in html only displays repeatedly the year 1970. The year 1970 is not even in the dataset.
How can I display my years from 1980 to 2019 correctly on the xAxis ?
That's expected, you're passing numbers to a scale that expects date objects:
const timeExtent = [1980, 2019];
let xScale = d3.scaleTime()
.domain(timeExtent);
console.log(xScale.domain());
<script src="https://d3js.org/d3.v7.min.js"></script>
That number will be passed internally to new Date
, which will treat that 2019 of yours not as the year 2019 but as 2019 milliseconds since 1 January 1970 UTC.
Instead, pass proper date objects to the scale:
const timeExtent = [1980, 2019];
const parser = d3.timeParse("%Y");
let xScale = d3.scaleTime()
.domain(timeExtent.map(parser));
console.log(xScale.domain());
<script src="https://d3js.org/d3.v7.min.js"></script>