GSinghLDN
GSinghLDN

Reputation: 181

Highcharts custom scaling on y axis - mix of linear and logarithmic

I am trying to use a logarithmic scale on my chart like below:

However, the outbound data is much lower than the inbound data. This doesnt show properly in the graph and makes it look like there is actually more outbound data than inbound.

I would like to have a linear scale upto the max value of the y axis (136) and some additional offest so basically upto 150 it should display linear scale and from there upto 600 (which shows the max capacity marker) to be logarithmic. Is this at all possible with Highcharts? Maybe the best function to use would be tickPositioner http://api.highcharts.com/highcharts#yAxis.tickPositioner.

The final desired result should be something like this:

Upvotes: 2

Views: 2274

Answers (2)

pkExec
pkExec

Reputation: 2066

For anyone with a similar problem, update for 2024:

Add this before you create the chart:

(function (H) {
    H.addEvent(H.Axis, 'afterInit', function() {
        const logarithmic = this.logarithmic;
        if (logarithmic){
            logarithmic.positiveValuesOnly = false;  
            const scale = (num, in_min, in_max, out_min, out_max) => {
                return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
            }
            
            const defaultGetLogTickPositions = logarithmic.getLogTickPositions;
            const defaultLog2lin = logarithmic.log2lin;
            const defaultLin2log = logarithmic.lin2log;
            const customTicks = this.options.customTicks;
            
            logarithmic.getLogTickPositions = function (interval, min, max, minor) {
                if (customTicks) {
                    let interval = customTicks[customTicks.length - 1] / (customTicks.length - 1);
                    return customTicks.map((v, i) => i * interval)
                }
                else {
                    return defaultGetLogTickPositions(interval, min, max, minor);
                }
            };

            logarithmic.log2lin = function (num) {
                if (customTicks) {
                    let tickInterval = ( customTicks[customTicks.length-1] / ( customTicks.length - 1 ) );
                    for (let i = 0; i < customTicks.length - 1; i++) {
                    if (num <= customTicks[i+1]) {
                        return scale(num, customTicks[i], customTicks[i+1], i * tickInterval, (i + 1) * tickInterval )
                    }
                    }
                    return 0;
                }
                else {
                    return defaultLog2lin(num);
                }

            };
            
            logarithmic.lin2log = function (num) {
                if (customTicks) {
                    let tickInterval = ( customTicks[customTicks.length-1] / ( customTicks.length - 1 ) );
                    for (let i = 0; i < customTicks.length - 1; i++) {
                    if (num <= tickInterval * (i + 1)) {
                        return scale(num, i * tickInterval, (i + 1) * tickInterval, customTicks[i], customTicks[i+1] )
                    }
                    }
                }
                else {
                    return defaultLin2log(num);
                }
            };
        }  
    });
}(Highcharts));

Now on your chart initialization, use this for yAxis:

{
    type: 'logarithmic',
    customTicks: [0,20,40,60,80,100,120,140,160,400,600]  //modify according to your data
}

Fiddle

Upvotes: 0

Mark
Mark

Reputation: 108522

Well, this is certainly a messy solution, but you could composite two graphs together:

enter image description here

Fiddle here.

$(function () {
        $('#containerBot').highcharts({
            chart: {marginTop: 1},
            title: {margin: 0, text: ''},
            yAxis: {max: 100},
            exporting: {enabled: false},
            series: [{
                name: 'One',
                data: [70.0, 60.9, 90.5, 140.5, 180.2, 210.5, 205.2, 260.5, 230.3, 180.3, 130.9, 90.6]
            }, {
                name: 'Two',
                data: [-0.2, 0.8, 50.7, 110.3, 170.0, 220.0, 240.8, 204.1, 200.1, 140.1, 80.6, 20.5]
            }]
        });
        $('#containerTop').highcharts({
            chart: {marginBottom: -1},
            title: {text: 'My Chart'},
            yAxis: {min: 100},
            xAxis: {labels: {enabled: false}},
            legend: {enabled: false},
            exporting: {enabled: false},
            credits: {enabled: false},
            series: [{
                name: 'One',
                data: [70.0, 60.9, 90.5, 140.5, 180.2, 210.5, 205.2, 260.5, 230.3, 180.3, 130.9, 90.6]
            }, {
                name: 'Two',
                data: [-0.2, 0.8, 50.7, 110.3, 170.0, 220.0, 240.8, 204.1, 200.1, 140.1, 80.6, 20.5]
            }]
        });
});

Upvotes: 2

Related Questions