]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Fix scale when data is all small numbers (#5723)
authorCarl Osterwisch <costerwi@gmail.com>
Sun, 16 Sep 2018 09:33:48 +0000 (05:33 -0400)
committerSimon Brunel <simonbrunel@users.noreply.github.com>
Sun, 16 Sep 2018 09:33:48 +0000 (11:33 +0200)
* Add test for correct handling of small numbers

* Calculate tick precision for arbitrarily small numbers

* Use scientific notation for very small tick numbers

* Calculate significant digits for exponential tick values

src/core/core.ticks.js
src/scales/scale.linearbase.js
test/specs/scale.linear.tests.js

index 3898842a49a6fceb684e41966a205efd56d43822..f63e525983a71c25c723d2d0b21eaa4977773244 100644 (file)
@@ -46,9 +46,15 @@ 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
+                                       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
+                                       tickString = tickValue.toFixed(numDecimal);
+                               }
                        } else {
                                tickString = '0'; // never show decimal places for 0
                        }
index c78dc64f298f15a385d4b6a3ffc52b85ba291cf4..7408eb9f98927604a7b86b9cd1b7a00ab71d1e9e 100644 (file)
@@ -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;
        }
index ab046078391eb592bbe7a8f235f68158a89ebd48..380feaac09d4532d42843889e99e50e8eedf4d8a 100644 (file)
@@ -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',