Reputation: 601
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.
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?
Upvotes: 2
Views: 887
Reputation: 601
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.
Upvotes: 3
Reputation: 16905
I assume your y-values are something like number of seconds? You could write an axisLabelFormatter for the y-axis to convert number of seconds to a string like "1h" or "30m".
The default y-axis ticker chooses nice values for whole numbers, e.g. 100, 200, 300, which aren't necessarily nice values for durations. To get that, as you say, you'll need to write your own ticker.
This isn't as hard as it sounds. The best documentation on tickers is here. The numericTicks
ticker is the simplest example.
Upvotes: 3