Skip to content

Commit

Permalink
Add scientific notation option
Browse files Browse the repository at this point in the history
and also deal with a few other corner cases on linear axis on Chartjs
plots. Closes issue #142
  • Loading branch information
Jisk Attema committed Mar 13, 2018
1 parent c444fb4 commit 62fe4cd
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/widgets/chartjs-scilinear-formatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Formatter for tick labels on a linear axis in chartjs
*
* Override the default behavious such that it:
* * switches to scientific notation for large numbers with a lot of 'trailing zeros': 1e25
* * only prints the trailing (least significant) digits when zoomin in: 100000000000.1 prints as '..000.1'
*
* see issue #142
*/
module.exports = function (tickValue, index, ticks) {
// Find the proper tick spacing
// if we have lots of ticks, don't use the ones
var delta = Math.abs(ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]);

if (tickValue === 0) {
return '0';
}

// Find the order of magnitude of the least significant digit
var leastSignificantOOM = Math.floor(Math.log10(delta));

// Find the order magnitude of the most significant digit
var logTicks = [];
ticks.forEach(function (value, i) {
if (value !== 0) {
logTicks.push(Math.log10(Math.abs(value)));
}
});
var mostSignificantOOM = Math.floor(Math.max.apply(Math, logTicks));

// We can chose between 3 different notations for '12.34':
// fixed precision: 12.34
// scientific notation: 1.234e1
// and truncated ..34
// find how long each notation would be, and chose the optimal one

// when using scientific notation (1,2303e2), how many digits would it take?
var totalNumberOfDigits = mostSignificantOOM + 1 - leastSignificantOOM;

// when using fixed notation (123.03), how many digits would it take?
var fixedNotationDitigts = 1 +
Math.max(0, mostSignificantOOM) + // digits before '.'
Math.max(0, Math.abs(leastSignificantOOM)); // digits after '.'

// when truncating the string to the last 5 digits, it is of course 5 digits

var tickString = '';
if (fixedNotationDitigts < 9) {
var numDecimal = Math.max(Math.min(-1 * leastSignificantOOM, 20), 0); // toFixed has a max of 20 decimal places
tickString = tickValue.toFixed(numDecimal);
} else if (totalNumberOfDigits < 9) {
tickString = tickValue.toExponential(totalNumberOfDigits - 1);
} else {
tickString = tickValue.toFixed(Math.max(0, -1 * leastSignificantOOM));
tickString = '..' + tickString.substring(tickString.length - 5, tickString.length);
}

return tickString;
};
4 changes: 4 additions & 0 deletions src/widgets/view-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ extendWithErrorBar(Chart, 'horizontalBar', 'horizontalBarError');
var extendWithDurationScale = require('./chartjs-duration-scale');
extendWithDurationScale(Chart);

// replace the default linear scale with a smarter formatter
var SciLinearFormatter = require('./chartjs-scilinear-formatter');
Chart.scaleService.updateScaleDefaults('linear', { ticks: { callback: SciLinearFormatter } });

var widgetEntry = AmpersandModel.extend({
props: {
modelType: {type: 'string', required: true},
Expand Down

0 comments on commit 62fe4cd

Please sign in to comment.