Search code examples
jquerydygraphsticker

plotting on a dygraph y-axis as time?


Is it possible to create a Time format on the y-axis of a Dygraph?

-> formats #s, #m, #h.
The graph needs to display in whole numbers and not something like 2.5h.

enter image description here

I assume this can be done through the dygraph ticker option though I'm not completely sure where to start as the dygraph always seems to like to split its granularity at certain values (time should be split 60s then at 60m).

Can someone point me in the right direction for writing my own Dygraph ticker?


Solution

  • So I finally got around to writing an answer!

    The easiest solution I found was to convert the amount (in seconds) to number of minutes or hours to which it then is split into nice intervals.

    I found that changing to the higher value looked best at when it was double -> so seconds only changed to minutes when there was time greater than 2 minutes.


    The ticker looks as so:

    function dygraphTimeTicker(min, max, pixels, opts, dygraph, vals) {
        //Bigger the physical size of the graph - the more ticks we want
        var stepsAim = Math.ceil(pixels / 50);
    
        var storemax = Number(max);
        var storemin = Number(min);
        var timeRatio, valueSuffix;
    
        //Display the ticks as seconds, minutes or hours?
        if (storemax <= 120) { // (seconds) max <= 2 Minutes
            valueSuffix = "s";
            timeRatio = 1;
        } else if (storemax <= 7200) { // (minutes) max <= 2 Hours
            valueSuffix = "m";
            timeRatio = 60;
        } else { // (hours)
            valueSuffix = "h";
            timeRatio = 3600;
        }
    
        var tempmax = storemax + (timeRatio - (storemax % timeRatio));
        var maxTime = tempmax / timeRatio;
    
        //give us an array of our 'nice' values
        var labelSteps = gaugeSteps(maxTime, stepsAim);
    
        var labelArray = [];
        for (var j = 0; j < labelSteps.length; j++) {
            labelArray.push({
                v: labelSteps[j] * timeRatio,
                label: labelSteps[j] + valueSuffix
            });
        }
    
        return labelArray;
    }
    

    The dygraphTimeTicker also implements these functions:

    //Give us a nice even numbers for our ticks
    function calculateEvenStepSize(range, targetSteps) {
        // calculate an initial guess at step size
        var tempStep = range / targetSteps;
    
        // get the magnitude of the step size
        var mag = Math.floor(Math.log(tempStep) / Math.log(10));
        var magPow = Math.pow(10, mag);
    
        // calculate most significant digit of the new step size
        var magMsd = Math.round(tempStep / magPow + 0.5);
    
        // promote the MSD to either 1, 2, or 5
        if (magMsd > 5)
            magMsd = 10;
        else if (magMsd > 2)
            magMsd = 5;
        else if (magMsd > 1)
            magMsd = 2;
    
        return magMsd * magPow;
    };
    
    //Give us the array of values we want displayed as 'major ticks'
    function gaugeSteps(max, step) {
        var steps = step || 10;
        var ticks = [];
    
        //if below steps then we don't want any decimals!
        if (max < steps) {
            for (var i = 0; i <= max; i++) {
                ticks.push(i);
            }
        } else {
            var tickSize = calculateEvenStepSize(max, steps);
            var loopAmount = Math.ceil(max / tickSize);
    
            for (i = 0; i < loopAmount + 1; i++) {
                ticks.push(i * tickSize);
            }
        }
    
        return ticks;
    }
    

    Initializing:

    new Dygraph(document.getElementById("graph"), data, {
        series: { 'Values': { axis: 'y1' } },
        ylabel: "Time",
        graphType: "Date",
        axes: {
            y: {
                ticker: dygraphTimeTicker,
                includeZero: true,
                valueFormatter: function(val, opts, lineName) {
                    //This here is your own formatter
                    return ValueToTime(val);
                }
            }
        }
    });
    

    I hope this helps someone else out there.