From 5abee89067c55e76ff2aa0a18af257e60b4d8702 Mon Sep 17 00:00:00 2001 From: Carl Osterwisch Date: Sat, 8 Sep 2018 09:29:50 -0400 Subject: [PATCH 1/4] Add test for correct handling of small numbers --- test/specs/scale.linear.tests.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/specs/scale.linear.tests.js b/test/specs/scale.linear.tests.js index ab046078391..380feaac09d 100644 --- a/test/specs/scale.linear.tests.js +++ b/test/specs/scale.linear.tests.js @@ -212,6 +212,31 @@ describe('Linear Scale', function() { expect(chart.scales.yScale0.max).toBe(90); }); + it('Should correctly determine the max & min data values for small numbers', function() { + var chart = window.acquireChart({ + type: 'bar', + data: { + datasets: [{ + yAxisID: 'yScale0', + data: [-1e-8, 3e-8, -4e-8, 6e-8] + }], + labels: ['a', 'b', 'c', 'd'] + }, + options: { + scales: { + yAxes: [{ + id: 'yScale0', + type: 'linear' + }] + } + } + }); + + expect(chart.scales.yScale0).not.toEqual(undefined); // must construct + expect(chart.scales.yScale0.min * 1e8).toBeCloseTo(-4); + expect(chart.scales.yScale0.max * 1e8).toBeCloseTo(6); + }); + it('Should correctly determine the max & min for scatter data', function() { var chart = window.acquireChart({ type: 'line', From 5c28251a6f6935b40c53b8cee4802338456abc12 Mon Sep 17 00:00:00 2001 From: Carl Osterwisch Date: Sat, 8 Sep 2018 11:08:45 -0400 Subject: [PATCH 2/4] Calculate tick precision for arbitrarily small numbers --- src/scales/scale.linearbase.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index c78dc64f298..7408eb9f989 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -54,7 +54,7 @@ function generateTicks(generationOptions, dataRange) { precision = 1; if (spacing < 1) { - precision = Math.pow(10, spacing.toString().length - 2); + precision = Math.pow(10, 1 - Math.floor(helpers.log10(spacing))); niceMin = Math.round(niceMin * precision) / precision; niceMax = Math.round(niceMax * precision) / precision; } From d03be0fd329f1b9d2a426e4a00a3641a132e8e9c Mon Sep 17 00:00:00 2001 From: Carl Osterwisch Date: Sat, 8 Sep 2018 11:09:53 -0400 Subject: [PATCH 3/4] Use scientific notation for very small tick numbers --- src/core/core.ticks.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/core.ticks.js b/src/core/core.ticks.js index 3898842a49a..eb40c0d27b5 100644 --- a/src/core/core.ticks.js +++ b/src/core/core.ticks.js @@ -46,9 +46,14 @@ module.exports = { var tickString = ''; if (tickValue !== 0) { - var numDecimal = -1 * Math.floor(logDelta); - numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places - tickString = tickValue.toFixed(numDecimal); + var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1])); + if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation + tickString = tickValue.toExponential(1); + } else { + var numDecimal = -1 * Math.floor(logDelta); + numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places + tickString = tickValue.toFixed(numDecimal); + } } else { tickString = '0'; // never show decimal places for 0 } From b5cc6eb4e9245559cfca21e35229ee0b92f7c721 Mon Sep 17 00:00:00 2001 From: Carl Osterwisch Date: Sat, 8 Sep 2018 16:00:19 -0400 Subject: [PATCH 4/4] Caclulate significant digits for exponential tick values --- src/core/core.ticks.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/core.ticks.js b/src/core/core.ticks.js index eb40c0d27b5..f63e525983a 100644 --- a/src/core/core.ticks.js +++ b/src/core/core.ticks.js @@ -48,7 +48,8 @@ module.exports = { if (tickValue !== 0) { var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1])); if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation - tickString = tickValue.toExponential(1); + var logTick = helpers.log10(Math.abs(tickValue)); + tickString = tickValue.toExponential(Math.floor(logTick) - Math.floor(logDelta)); } else { var numDecimal = -1 * Math.floor(logDelta); numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places