Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shorten months ticks on x axis

Tags:

How can I shorten the months label, from October to Oct.

When the default graph shows October, it should display Oct. and the years should be kept.

I think I should use

.tickFormat(d3.timeFormat("%b"))

but when I use it, the years are not shown.

How can I apply the tickFormat only if the legend displays a month?

like image 643
stackk Avatar asked Dec 15 '17 09:12

stackk


People also ask

How to change axis Label intervals in excel?

On the Format tab, in the Current Selection group, click Format Selection. Under Axis Options, do one or both of the following: To change the interval between axis labels, under Interval between labels, click Specify interval unit, and then in the text box, type the number that you want.

What is the horizontal axis of a chart?

The horizontal (category) axis, also known as the x axis, of a chart displays text labels instead of numeric intervals and provides fewer scaling options than are available for a vertical (value) axis, also known as the y axis, of the chart.


1 Answers

The problem with such customisations is that in D3 axes are automatically generated, and setting some things like the exact amount of ticks can be frustratingly difficult. The situation is even more complicated in a time scale, which makes your case worse: in a time scale it's hard to know beforehand how the ticks will be formatted.

As you already know, converting all ticks to the month's abbreviation is easy. However, if you want to keep the default structure and change only the ticks with months, you'll have to modify the axis after it was created. In this example, using each.

So, let's first create a default axis. Here it is:

var svg = d3.select("svg");
var scale = d3.scaleTime()
  .range([20, 480])
  .domain([new Date("06-01-2016"), new Date("06-01-2017")]);

var axis = d3.axisBottom(scale)
  .ticks(4);

var gX = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(axis);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>

As you can see, we have four ticks: three ticks with full months and one tick with the year.

Now let's check the format of each tick using this and comparing with the datum (d), converting the text to abbreviated month name only if it is already a month:

gX.selectAll(".tick").each(function(d) {
  if (this.textContent === d3.timeFormat("%B")(d)) {
    d3.select(this).select("text").text(d3.timeFormat("%b")(d))
  }
})

Here is the result:

var svg = d3.select("svg");
var scale = d3.scaleTime()
  .range([20, 480])
  .domain([new Date("06-01-2016"), new Date("06-01-2017")]);

var axis = d3.axisBottom(scale)
  .ticks(4);

var gX = svg.append("g")
  .attr("transform", "translate(0,50)")
  .call(axis);

gX.selectAll(".tick").each(function(d) {
  if (this.textContent === d3.timeFormat("%B")(d)) {
    d3.select(this).select("text").text(d3.timeFormat("%b")(d))
  }
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>
like image 133
Gerardo Furtado Avatar answered Sep 23 '22 12:09

Gerardo Furtado