mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-02-01 17:47:09 +00:00
Fix generateTicks when working with tiny numbers (#5948)
This commit is contained in:
parent
820debf452
commit
9d7eacd251
@ -4,6 +4,7 @@ var helpers = require('../helpers/index');
|
||||
var Scale = require('../core/core.scale');
|
||||
|
||||
var noop = helpers.noop;
|
||||
var isNullOrUndef = helpers.isNullOrUndef;
|
||||
|
||||
/**
|
||||
* Generate a set of linear ticks
|
||||
@ -17,24 +18,31 @@ function generateTicks(generationOptions, dataRange) {
|
||||
// "nice number" algorithm. See https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
|
||||
// for details.
|
||||
|
||||
var MIN_SPACING = 1e-14;
|
||||
var stepSize = generationOptions.stepSize;
|
||||
var unit = stepSize || 1;
|
||||
var maxNumSpaces = generationOptions.maxTicks - 1;
|
||||
var min = generationOptions.min;
|
||||
var max = generationOptions.max;
|
||||
var precision = generationOptions.precision;
|
||||
var spacing, factor, niceMin, niceMax, numSpaces;
|
||||
var rmin = dataRange.min;
|
||||
var rmax = dataRange.max;
|
||||
var spacing = helpers.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit;
|
||||
var factor, niceMin, niceMax, numSpaces;
|
||||
|
||||
// spacing is set to a nice number of the dataRange divided by maxNumSpaces.
|
||||
// stepSize is used as a minimum unit if it is specified.
|
||||
spacing = helpers.niceNum((dataRange.max - dataRange.min) / maxNumSpaces / unit) * unit;
|
||||
numSpaces = Math.ceil(dataRange.max / spacing) - Math.floor(dataRange.min / spacing);
|
||||
// Beyond MIN_SPACING floating point numbers being to lose precision
|
||||
// such that we can't do the math necessary to generate ticks
|
||||
if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) {
|
||||
return [rmin, rmax];
|
||||
}
|
||||
|
||||
numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
|
||||
if (numSpaces > maxNumSpaces) {
|
||||
// If the calculated num of spaces exceeds maxNumSpaces, recalculate it
|
||||
spacing = helpers.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit;
|
||||
}
|
||||
|
||||
if (stepSize || helpers.isNullOrUndef(precision)) {
|
||||
if (stepSize || isNullOrUndef(precision)) {
|
||||
// If a precision is not specified, calculate factor based on spacing
|
||||
factor = Math.pow(10, helpers.decimalPlaces(spacing));
|
||||
} else {
|
||||
@ -43,16 +51,16 @@ function generateTicks(generationOptions, dataRange) {
|
||||
spacing = Math.ceil(spacing * factor) / factor;
|
||||
}
|
||||
|
||||
niceMin = Math.floor(dataRange.min / spacing) * spacing;
|
||||
niceMax = Math.ceil(dataRange.max / spacing) * spacing;
|
||||
niceMin = Math.floor(rmin / spacing) * spacing;
|
||||
niceMax = Math.ceil(rmax / spacing) * spacing;
|
||||
|
||||
// If min, max and stepSize is set and they make an evenly spaced scale use it.
|
||||
if (stepSize) {
|
||||
// If very close to our whole number, use it.
|
||||
if (!helpers.isNullOrUndef(min) && helpers.almostWhole(min / spacing, spacing / 1000)) {
|
||||
if (!isNullOrUndef(min) && helpers.almostWhole(min / spacing, spacing / 1000)) {
|
||||
niceMin = min;
|
||||
}
|
||||
if (!helpers.isNullOrUndef(max) && helpers.almostWhole(max / spacing, spacing / 1000)) {
|
||||
if (!isNullOrUndef(max) && helpers.almostWhole(max / spacing, spacing / 1000)) {
|
||||
niceMax = max;
|
||||
}
|
||||
}
|
||||
@ -67,11 +75,11 @@ function generateTicks(generationOptions, dataRange) {
|
||||
|
||||
niceMin = Math.round(niceMin * factor) / factor;
|
||||
niceMax = Math.round(niceMax * factor) / factor;
|
||||
ticks.push(helpers.isNullOrUndef(min) ? niceMin : min);
|
||||
ticks.push(isNullOrUndef(min) ? niceMin : min);
|
||||
for (var j = 1; j < numSpaces; ++j) {
|
||||
ticks.push(Math.round((niceMin + j * spacing) * factor) / factor);
|
||||
}
|
||||
ticks.push(helpers.isNullOrUndef(max) ? niceMax : max);
|
||||
ticks.push(isNullOrUndef(max) ? niceMax : max);
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
@ -1170,4 +1170,29 @@ describe('Linear Scale', function() {
|
||||
expect(data[0]._model.base + minBarLength).toEqual(data[0]._model.x);
|
||||
expect(data[1]._model.base - minBarLength).toEqual(data[1]._model.x);
|
||||
});
|
||||
|
||||
it('Should generate max and min that are not equal when data contains values that are very close to each other', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'scatter',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
{x: 1, y: 1.8548483304974972},
|
||||
{x: 2, y: 1.8548483304974974},
|
||||
]
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
id: 'yScale0',
|
||||
type: 'linear',
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.scales.yScale0).not.toEqual(undefined); // must construct
|
||||
expect(chart.scales.yScale0.max).toBeGreaterThan(chart.scales.yScale0.min);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user