From d50549d6fd9f2b8e9ac3427efb3385e5a19b2ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Wed, 31 Mar 2021 16:42:26 +0200 Subject: [PATCH] In band scales, avoid collapsing with round=true when the range is too narrow to accommodate the domain. fixes https://github.com/d3/d3-scale/issues/242 --- src/band.js | 6 ++++-- test/band-test.js | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/band.js b/src/band.js index 88e1fbd..c6f3212 100644 --- a/src/band.js +++ b/src/band.js @@ -23,10 +23,12 @@ export default function band() { start = reverse ? r1 : r0, stop = reverse ? r0 : r1; step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); - if (round) step = Math.floor(step); + var r = round && step >= 1; + if (r) step = Math.floor(step); start += (stop - start - step * (n - paddingInner)) * align; bandwidth = step * (1 - paddingInner); - if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); + if (round) start = Math.round(start); + if (r) bandwidth = Math.round(bandwidth); var values = sequence(n).map(function(i) { return start + step * i; }); return ordinalRange(reverse ? values.reverse() : values); } diff --git a/test/band-test.js b/test/band-test.js index 2fef80e..99a0dcb 100644 --- a/test/band-test.js +++ b/test/band-test.js @@ -181,6 +181,23 @@ tape("band.rangeRound(values) coerces values to numbers", function(test) { test.end(); }); +tape("band.round is ignored when the range is too small and the scale would collapse", function(test) { + var domain = ["A", "B", "C", "D", "E", "F"]; + var s1 = scale.scaleBand().domain(domain).rangeRound([0, 3]); + test.deepEqual(domain.map(s1), [ 0, 0.5, 1, 1.5, 2, 2.5 ]); + test.equal(s1.bandwidth(), 0.5); + var s2 = scale.scaleBand().domain(domain).rangeRound([0, 30]); + test.deepEqual(domain.map(s2), [ 0, 5, 10, 15, 20, 25 ]); + var s3 = scale.scaleBand().domain(domain).rangeRound([0, 10]); + test.deepEqual(domain.map(s3), [ 2, 3, 4, 5, 6, 7 ]); + var s4 = scale.scaleBand().domain(domain).range([0, 3]).round(true); + test.deepEqual(domain.map(s4), [ 0, 0.5, 1, 1.5, 2, 2.5 ]); + var s5 = scale.scaleBand().domain(domain).range([0, 1.5]).round(true); + test.deepEqual(domain.map(s5), [ 0, 0.25, 0.5, 0.75, 1, 1.25 ]); + test.equal(s5.bandwidth(), 0.25); + test.end(); +}); + tape("band.paddingInner(p) specifies the inner padding p", function(test) { var s = scale.scaleBand().domain(["a", "b", "c"]).range([120, 0]).paddingInner(0.1).round(true); test.deepEqual(s.domain().map(s), [83, 42, 1]);