Search code examples
chartsdrawflot

How to draw a chart with nonlinear x-axis (logarithmic scale)?


I am trying to draw a Critical Power Chart like this: enter image description here

The data I get is linear. One value for every second from 1 up to 18000. I have no clue how to teach flot to draw an non-linear x-axis. I tried to set custom ticks, but this seems to just have impact to the labels, not the line.

The x axis ticks will always be the same and don't need to be calculated:

[1s,5s,15s,30s,1m,2m,3m,5m,10m,20m30m,1h,2h,3h,5h]

Playground including tons of data: https://jsfiddle.net/ogeo2ygx/6/

Code:

$.plot($("#cpChart"), [{data: data,label: "Critical Power", labelBoxBorderColor: 0, color: '#cbcbcb',yaxis:1,lines: { show: true, fill: true } }], {
        xaxes: [{
            //here should be some Magic to Draw an nice Critical Power Chart
            tickFormatter: (t, v) => {
                return t + "s";
            }
        }],
        yaxes: [{
            alignTicksWithAxis: 1,
            position: "left",
            tickFormatter: (t, v) => {
                return t.toFixed(0) + " Watt"
            }
        }],
        legend: {
            position: 'sw',
            labelBoxBorderColor: 0
        },
        colors: ["#1ab394"],
        grid: {
            color: "#999999",
            clickable: true,
            tickColor: "#D4D4D4",
            borderWidth: 0,
            hoverable: true
        }
    });

Solution

  • You can achieve that (which is called logarithmic scale) with two steps:

    1. Transform the x-axis values using the Math.log function (with a +1 because the logarithm of zero is -infinity).
    2. Define a custom ticks array with your ticks.

    See the documentation for more information. Relevant code:

    xaxes: [{
        ticks: [[1, '1s'],[5, '5s'], [15, '15s'],[30, '30s'],[60, '1m'],[120, '2m'],[180, '3m'], [300, '5m'], [600, '10m'], [1200, '20m'], [1800, '30m'],[3600, '1h'], [7200, '2h'], [10800, '3h'], [18000, '5h']],
        transform: (x) => { return Math.log(1 + x); },
        inverseTransform: (x) => { return Math.exp(x) - 1; }
    }],
    

    Updated fiddle: https://jsfiddle.net/ogeo2ygx/8/