2

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.

xAxis output

How can I display my years from 1980 to 2019 correctly on the xAxis ?

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Jakob QN
  • 21
  • 3

1 Answers1

1

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>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171