damseldeebi
damseldeebi

Reputation: 137

highchart place x-axis labels in between ticks on a datetime axis

Using various posts/questions in SO as reference I created a scatter highchart jsfiddle

xAxis: {
        opposite:true,
        type: 'datetime',
        gridLineWidth: 1,
        gridLineDashStyle: 'ShortDot',
        gridLineColor:'black',
        alternateGridColor: 'lightgrey',
        tickInterval: 3 * 30 * 24 * 3600 * 1000, // 1 quarter
        labels: {
            //align: "left",
            //padding:200,
            formatter: function () {
                var s = "";
                if (Highcharts.dateFormat('%b', this.value) == 'Jan') {
                    s = s + "Q1"
                };
                if (Highcharts.dateFormat('%b', this.value) == 'Apr') {
                    s = s + "Q2"
                };
                if (Highcharts.dateFormat('%b', this.value) == 'Jul') {
                    s = s + "Q3"
                };
                if (Highcharts.dateFormat('%b', this.value) == 'Oct') {
                    s = s + "Q4"
                };
                s = s + " " + Highcharts.dateFormat('%Y', this.value);
                return s;
            }
        },
        plotLines: [{
            color: 'red', // Color value
            value: now, // Value of where the line will appear
            width: 2, // Width of the line
            label: {
                text: 'Now',
                align: 'center',
                verticalAlign: 'bottom',
                y: +20,
                rotation: 0
            }
        }]
    },

But I'm struck with having the X-axis label positioned near the tick. How to move to middle of the grid?

existing chart

Is there anyway I can achieve the below? expected result

I tried align, padding but didn't help. When the timeline increases I should still have the labels positioned in the middle. should I do something with tickInterval? It might be a simple property I'm missing.

I found this link jsfiddle which addresses my concern but with 2 x-axis and I'm populating the data from a list.

Upvotes: 0

Views: 1683

Answers (1)

Charles Clayton
Charles Clayton

Reputation: 17946

I implemented Christopher Cortez' solution found here:

enter image description here

However, also changed to to fire on the highcharts load event, rather than the callback, and I've changed it to be recalled when the HighCharts redraw event is fired, so that they stay aligned when the page is resized.

$('#container').highcharts({
        chart: {
            defaultSeriesType: 'scatter',
            events: {
                 load: centerLabels,
                 redraw: centerLabels                    
            }
        },

        /* ... all the other options ...*/

 });

Where

function centerLabels(chart) {        
    var $container = $(chart.target.container); 
    var axes = chart.target.axes;

    var $labels = $container.find('.highcharts-axis-labels .timeline_label');
    var $thisLabel, $nextLabel, thisXPos, nextXPos, delta, newXPos;

    $labels.each(function () {
        $thisLabel = $(this).parent('span');
        thisXPos = parseInt($thisLabel.css('left'));

        $nextLabel = $thisLabel.next();
        // next position is either a label or the end of the axis
        nextXPos = $nextLabel.length ? parseInt($nextLabel.css('left')) : axes[0].left + axes[0].width;
        delta = (nextXPos - thisXPos) / 2.0;
        newXPos = thisXPos + delta;

        // remove the last label if it won't fit
        if ($nextLabel.length || $(this).width() + newXPos < nextXPos) {
            $thisLabel.css('left', newXPos + 'px');
        } else {
            $thisLabel.remove();
        }
    });
}

JSFiddle

Upvotes: 1

Related Questions