vijayst
vijayst

Reputation: 21826

The axis label at x=0 does not show up

I am using D3 to draw a line chart. The value at x=0 does not show up.

enter image description here

The code for the axis is shown below.

const xScale = d3
    .scaleTime()
    .domain(d3.extent(data[0].series, d => d.time))
    .range([xPadding, width - xPadding]);

const xAxis = d3
    .axisBottom(xScale)
    .ticks(4)
    .tickSizeOuter(0)
    .tickSizeInner(0)
    .tickFormat(d3.timeFormat('%Y'));

I am not sure why it is not showing up the label at x=0, which is 2014. On checking the SVG, only three tick marks are displayed, but the one at x=0 is not in the SVG element.

CodePen for this: https://codepen.io/vijayst/pen/bLJYoK?editors=1111

Upvotes: 2

Views: 1579

Answers (1)

Xavier Guihot
Xavier Guihot

Reputation: 61646

I see different solutions which have their pros and cons. The third solution should be the cleanest and most generic.

Add the left tick manually:

Since d3 handles itself the location of x-axis ticks, one way of doing so would (if the data set is fixed) would be to manually add the missing tick:

svg 
  .append("g")
  .append("text")
  .text("2014-02-01") // can be retrieved from data instead of being harcoded
  .style("font-size", 10)
  .style("font-family", "sans-serif")
  .attr("transform", "translate(0," + (height - yPadding + 10) + ")")

which looks great, but in this case you might have problems if for a given dataset, d3 chooses to display a tick close to the left edge of the axis. Both d3's tick and the label we've included could overlap.


Modify the x-scale to start before the first day of the year:

An other solution would be to increase the x-axis range on the left to make it start one month before the first point's date. To try this out, we can replace:

.domain(d3.extent(data[0].series, d => d.time))

with

.domain(d3.extent([new Date(2013, 12), new Date(2019, 1)]))

which allow d3 to legitimately include a "year-tick" for 2014 at the begin of the x-axis.

but in this case, the first point will have an offset with the begin of the x-axis range.


Push a specific tick to ticks auto-generated by d3:

An other solution: we can push a specific tick to the ticks auto-generated by d3. But this requires to modify the format of ticks to "%Y-%m".

In order to do this, replace:

.tickFormat(d3.timeFormat("%Y"));

with

.tickFormat(d3.timeFormat("%Y-%m"));

we can then push a new specific tick to the set of ticks generated by d3:

var ticks = xScale.ticks();
ticks.push(new Date(2014, 1, 1));
xAxis.tickValues(ticks);

and include some padding in the left and the right of the chart since now tick labels have a part displayed outside the graph:

const svg = d3
  .select("#chart")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .style("padding-left", 15)
  .style("padding-right", 15);

Upvotes: 2

Related Questions