From 34c5c84cf8f343e3bce81a6aabe072165101ec52 Mon Sep 17 00:00:00 2001 From: syawqy Date: Mon, 30 Mar 2026 23:46:23 +0700 Subject: [PATCH] fix(linear-scale): respect stepSize for non-divisible min/max ranges --- src/scales/scale.linearbase.js | 5 +++- test/specs/scale.linear.tests.js | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index d2da5501eb7..e91fce00585 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -66,7 +66,10 @@ function generateTicks(generationOptions, dataRange) { niceMax = rmax; } - if (minDefined && maxDefined && step && almostWhole((max - min) / step, spacing / 1000)) { + const stepCount = step ? (max - min) / step : 0; + const stepCountEpsilon = Math.max(Math.abs(stepCount) * Number.EPSILON, 1e-14); + + if (minDefined && maxDefined && step && almostWhole(stepCount, stepCountEpsilon)) { // Case 1: If min, max and stepSize are set and they make an evenly spaced scale use it. // spacing = step; // numSpaces = (max - min) / spacing; diff --git a/test/specs/scale.linear.tests.js b/test/specs/scale.linear.tests.js index a8ad53995b1..e7f48b464c8 100644 --- a/test/specs/scale.linear.tests.js +++ b/test/specs/scale.linear.tests.js @@ -684,6 +684,48 @@ describe('Linear Scale', function() { expect(getLabels(chart.scales.y)).toEqual(['1', '3', '5', '7', '9', '11']); }); + it('Should use stepSize increments and keep max as the final shorter interval', function() { + var chart = window.acquireChart({ + type: 'bar', + options: { + scales: { + y: { + type: 'linear', + min: 0, + max: 3333, + ticks: { + stepSize: 500 + } + } + } + } + }); + + expect(chart.scales.y.ticks.map(tick => tick.value)).toEqual([ + 0, 500, 1000, 1500, 2000, 2500, 3000, 3333 + ]); + }); + + it('Should use stepSize for floating point ranges that are effectively divisible', function() { + var chart = window.acquireChart({ + type: 'bar', + options: { + scales: { + y: { + type: 'linear', + min: 0, + max: 0.3, + ticks: { + stepSize: 0.1 + } + } + } + } + }); + + expect(chart.scales.y.ticks.map(tick => +tick.value.toFixed(1))).toEqual([0, 0.1, 0.2, 0.3]); + }); + it('Should not generate any ticks > max if max is specified', function() { var chart = window.acquireChart({ type: 'line',