From 306c319c447654bcc6fd94060a81d64906db071b Mon Sep 17 00:00:00 2001 From: Michael Hedman Date: Tue, 23 Oct 2018 13:46:03 +0200 Subject: [PATCH 1/2] Fix for issue 7438 by improving getRoundNum() function. Added corresponding unit test and debug page. --- debug/7438.html | 34 ++++++++++++++++++++++++++++++ src/ui/control/scale_control.js | 9 +++++++- test/unit/ui/control/scale.test.js | 13 ++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 debug/7438.html diff --git a/debug/7438.html b/debug/7438.html new file mode 100644 index 00000000000..238152a0ade --- /dev/null +++ b/debug/7438.html @@ -0,0 +1,34 @@ + + + + Mapbox GL JS debug page + + + + + + + +
+ + + + + + diff --git a/src/ui/control/scale_control.js b/src/ui/control/scale_control.js index e53b8bf7b9b..2cd09f31945 100644 --- a/src/ui/control/scale_control.js +++ b/src/ui/control/scale_control.js @@ -147,7 +147,14 @@ function getRoundNum(num) { d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : - d >= 2 ? 2 : 1; + d >= 2 ? 2 : + d >= 1 ? 1 : + d >= 0.1 ? Math.round(d * 10) / 10 : + d >= 0.01 ? Math.round(d * 100) / 100 : + d >= 0.001 ? Math.round(d * 1000) / 1000 : + d >= 0.0001 ? Math.round(d * 10000) / 10000 : + d >= 0.00001 ? Math.round(d * 100000) / 100000 : Math.round(d * 1000000) / 1000000; + // Could go on forever of course, depending on the unit used. But this is good enough for 'imperial', 'metric' and 'nautical'. return pow10 * d; } diff --git a/test/unit/ui/control/scale.test.js b/test/unit/ui/control/scale.test.js index e98ce0da161..b96a7295d3b 100644 --- a/test/unit/ui/control/scale.test.js +++ b/test/unit/ui/control/scale.test.js @@ -33,3 +33,16 @@ test('ScaleControl should change unit of distance after calling setUnit', (t) => t.match(contents, /mi/); t.end(); }); + +test('ScaleControl should respect the maxWidth regardless of the unit and actual scale', (t) => { + const map = createMap(t); + const maxWidth = 100; + const scale = new ScaleControl({ maxWidth: maxWidth, unit: 'nautical' }); + const selector = '.mapboxgl-ctrl-bottom-left .mapboxgl-ctrl-scale'; + map.addControl(scale); + map.setZoom(12.5); + + const el = map.getContainer().querySelector(selector); + t.ok(parseFloat(el.style.width, 10) <= maxWidth, 'ScaleControl respects maxWidth'); + t.end(); +}); From e97e68ecfbc76849bac66832dfafd348c8787d53 Mon Sep 17 00:00:00 2001 From: Michael Hedman Date: Tue, 23 Oct 2018 15:37:35 +0200 Subject: [PATCH 2/2] Generalized calculation of decimal round number. --- src/ui/control/scale_control.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/ui/control/scale_control.js b/src/ui/control/scale_control.js index 2cd09f31945..021a1fe4547 100644 --- a/src/ui/control/scale_control.js +++ b/src/ui/control/scale_control.js @@ -140,6 +140,11 @@ function getDistance(latlng1, latlng2) { } +function getDecimalRoundNum(d) { + const multiplier = Math.pow(10, Math.ceil(-Math.log(d) / Math.LN10)); + return Math.round(d * multiplier) / multiplier; +} + function getRoundNum(num) { const pow10 = Math.pow(10, (`${Math.floor(num)}`).length - 1); let d = num / pow10; @@ -148,13 +153,7 @@ function getRoundNum(num) { d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : - d >= 1 ? 1 : - d >= 0.1 ? Math.round(d * 10) / 10 : - d >= 0.01 ? Math.round(d * 100) / 100 : - d >= 0.001 ? Math.round(d * 1000) / 1000 : - d >= 0.0001 ? Math.round(d * 10000) / 10000 : - d >= 0.00001 ? Math.round(d * 100000) / 100000 : Math.round(d * 1000000) / 1000000; - // Could go on forever of course, depending on the unit used. But this is good enough for 'imperial', 'metric' and 'nautical'. + d >= 1 ? 1 : getDecimalRoundNum(d); return pow10 * d; }