From: Jukka Kurkela Date: Fri, 5 Mar 2021 00:37:46 +0000 (+0200) Subject: Linear: Skip ticks that would overlap with min/max (#8569) X-Git-Tag: v3.0.0-beta.13~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=24b14193b362c59b4d4f809031a5164e34606067;p=thirdparty%2FChart.js.git Linear: Skip ticks that would overlap with min/max (#8569) --- diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index fe4391568..6d8f1e1a3 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -42,12 +42,14 @@ function generateTicks(generationOptions, dataRange) { const unit = stepSize || 1; const maxNumSpaces = generationOptions.maxTicks - 1; const {min: rmin, max: rmax} = dataRange; + const minDefined = !isNullOrUndef(min); + const maxDefined = !isNullOrUndef(max); let spacing = niceNum((rmax - rmin) / maxNumSpaces / unit) * unit; let factor, niceMin, niceMax, numSpaces; // 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)) { + if (spacing < MIN_SPACING && !minDefined && !maxDefined) { return [{value: rmin}, {value: rmax}]; } @@ -70,7 +72,7 @@ function generateTicks(generationOptions, dataRange) { niceMax = Math.ceil(rmax / spacing) * spacing; // If min, max and stepSize is set and they make an evenly spaced scale use it. - if (stepSize && !isNullOrUndef(min) && !isNullOrUndef(max)) { + if (stepSize && minDefined && maxDefined) { // If very close to our whole number, use it. if (almostWhole((max - min) / stepSize, spacing / 1000)) { niceMin = min; @@ -88,11 +90,34 @@ function generateTicks(generationOptions, dataRange) { niceMin = Math.round(niceMin * factor) / factor; niceMax = Math.round(niceMax * factor) / factor; - ticks.push({value: isNullOrUndef(min) ? niceMin : min}); - for (let j = 1; j < numSpaces; ++j) { + + let j = 0; + if (minDefined) { + ticks.push({value: min}); + // If the niceMin is smaller than min, skip it + if (niceMin < min) { + j++; + } + // If the next nice tick is close to min, skip that too + if (almostWhole(Math.round((niceMin + j * spacing) * factor) / factor / min, spacing / 1000)) { + j++; + } + } + + for (; j < numSpaces; ++j) { ticks.push({value: Math.round((niceMin + j * spacing) * factor) / factor}); } - ticks.push({value: isNullOrUndef(max) ? niceMax : max}); + + if (maxDefined) { + // If the previous tick is close to max, replace it with max, else add max + if (almostWhole(ticks[ticks.length - 1].value / max, spacing / 1000)) { + ticks[ticks.length - 1].value = max; + } else { + ticks.push({value: max}); + } + } else { + ticks.push({value: niceMax}); + } return ticks; } diff --git a/test/fixtures/scale.linear/min-max-skip.js b/test/fixtures/scale.linear/min-max-skip.js new file mode 100644 index 000000000..03fee6f93 --- /dev/null +++ b/test/fixtures/scale.linear/min-max-skip.js @@ -0,0 +1,20 @@ +module.exports = { + description: 'https://github.com/chartjs/Chart.js/issues/7734', + config: { + type: 'line', + options: { + scales: { + y: { + max: 1225.2, + min: 369.5, + }, + x: { + display: false + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/scale.linear/min-max-skip.png b/test/fixtures/scale.linear/min-max-skip.png new file mode 100644 index 000000000..9141f8d20 Binary files /dev/null and b/test/fixtures/scale.linear/min-max-skip.png differ diff --git a/test/specs/scale.radialLinear.tests.js b/test/specs/scale.radialLinear.tests.js index 745e95d1a..e70fb9494 100644 --- a/test/specs/scale.radialLinear.tests.js +++ b/test/specs/scale.radialLinear.tests.js @@ -200,7 +200,7 @@ describe('Test the radial linear scale', function() { expect(chart.scales.r.min).toBe(-1010); expect(chart.scales.r.max).toBe(1010); - expect(getLabels(chart.scales.r)).toEqual(['-1,010', '-1,000', '-500', '0', '500', '1,000', '1,010']); + expect(getLabels(chart.scales.r)).toEqual(['-1,010', '-500', '0', '500', '1,010']); }); it('should forcibly include 0 in the range if the beginAtZero option is used', function() {