Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highcharts: xAxis yearly labels centered between ticks

Tags:

highcharts

I am drawing a line chart with monthly data points. However, I want the scale to display year strings only. So far, so easy. However, as far as I can see, Highcharts will always draw the xAxis labels relative to the ticks... and I am required to display them centered between ticks. Is there some simple way of doing this that I am missing, please...?

like image 226
user1617662 Avatar asked Apr 08 '13 12:04

user1617662


2 Answers

According to my understanding, the behavior you desire is:
http://jsfiddle.net/msjaiswal/U45Sr/2/

Let me break down the solution :
1. Monthly Data Points
One data point corresponding to one month :

var data = [
    [Date.UTC(2003,1),0.872],
    [Date.UTC(2003,2),0.8714],
    [Date.UTC(2003,3),0.8638],
    [Date.UTC(2003,4),0.8567],
    [Date.UTC(2003,5),0.8536],
    [Date.UTC(2003,6),0.8564],
    ..
]

2. Scale to display only yearly ticks
Use chart options like this:

        xAxis: {
        minRange : 30 * 24 * 3600 * 1000, //
        minTickInterval: 12* 30 * 24 * 3600 * 1000 // An year
    },
like image 137
Mayank Jaiswal Avatar answered Nov 05 '22 06:11

Mayank Jaiswal


There is no simple, out-of-the-box solution. You have to use events and reposition the labels accordingly. Here is a sample solution that also works when resizing the browser window (or otherwise forcing the chart to redraw), even when the tick count changes: http://jsfiddle.net/McNetic/eyyom2qg/3/

It works by attaching the same event handler to both the load and the redraw events:

$('#container').highcharts({
  chart: {
    events: {
      load: fixLabels,
      redraw: fixLabels
    }
  },
[...]

The handler itself looks like this:

  var fixLabels = function() {
  var labels = $('div.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
    return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
  });
  labels.css('margin-left', 
    (parseInt($(labels.get(1)).css('left')) - parseInt($(labels.get(0)).css('left'))) / 2
  );
  $(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};

Basically, it works like this:

  1. Get all existing labels (when redrawn, this includes newly added ones). 2. Sort by css property 'left' (they are not sorted this way after some redrawing)
  2. Calculate offset between the first two labels (the offset is the same for all labels)
  3. Set half of the offset as margin-left of all labels, effectively shifting them half the offset to the right.
  4. Remove the rightmost label (moved outside of chart, by sometimes partly visible).
like image 32
Nicolai Ehemann Avatar answered Nov 05 '22 06:11

Nicolai Ehemann