From aff459bc021a8cdd517917838f59c367210beb45 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 1 Apr 2022 13:26:18 +0200 Subject: [PATCH 1/3] Add optional maxWidth for ScaleLine control --- src/ol/control/ScaleLine.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ol/control/ScaleLine.js b/src/ol/control/ScaleLine.js index d97f29d33e..9ea269c2a1 100644 --- a/src/ol/control/ScaleLine.js +++ b/src/ol/control/ScaleLine.js @@ -51,6 +51,8 @@ const DEFAULT_DPI = 25.4 / 0.28; * @property {string} [className='ol-scale-line'] CSS Class name. * @property {number} [minWidth=64] Minimum width in pixels at the OGC default dpi. The width will be * adjusted to match the dpi used. + * @property {number|undefined} [maxWidth=undefined] Maximum width in pixels at the OGC default dpi. The width will be + * adjusted to match the dpi used. * @property {function(import("../MapEvent.js").default):void} [render] Function called when the control * should be re-rendered. This is called in a `requestAnimationFrame` callback. * @property {HTMLElement|string} [target] Specify a target if you want the control @@ -136,6 +138,12 @@ class ScaleLine extends Control { */ this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64; + /** + * @private + * @type {number|undefined} + */ + this.maxWidth_ = options.maxWidth; + /** * @private * @type {boolean} @@ -249,6 +257,11 @@ class ScaleLine extends Control { const minWidth = (this.minWidth_ * (this.dpi_ || DEFAULT_DPI)) / DEFAULT_DPI; + const maxWidth = + this.maxWidth_ !== undefined + ? (this.maxWidth_ * (this.dpi_ || DEFAULT_DPI)) / DEFAULT_DPI + : undefined; + let nominalCount = minWidth * pointResolution; let suffix = ''; if (units == Units.DEGREES) { @@ -307,6 +320,7 @@ class ScaleLine extends Control { let i = 3 * Math.floor(Math.log(minWidth * pointResolution) / Math.log(10)); let count, width, decimalCount; + let previousCount, previousWidth, previousDecimalCount; while (true) { decimalCount = Math.floor(i / 3); const decimal = Math.pow(10, decimalCount); @@ -316,9 +330,18 @@ class ScaleLine extends Control { this.element.style.display = 'none'; this.renderedVisible_ = false; return; + } + if (maxWidth !== undefined && width >= maxWidth) { + count = previousCount; + width = previousWidth; + decimalCount = previousDecimalCount; + break; } else if (width >= minWidth) { break; } + previousCount = count; + previousWidth = width; + previousDecimalCount = decimalCount; ++i; } let html; From 5d5deee5177b5da6f160498ad326effaad858129 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 1 Apr 2022 13:48:55 +0200 Subject: [PATCH 2/3] Update src/ol/control/ScaleLine.js Co-authored-by: Andreas Hocevar --- src/ol/control/ScaleLine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/control/ScaleLine.js b/src/ol/control/ScaleLine.js index 9ea269c2a1..b4f91201b7 100644 --- a/src/ol/control/ScaleLine.js +++ b/src/ol/control/ScaleLine.js @@ -51,7 +51,7 @@ const DEFAULT_DPI = 25.4 / 0.28; * @property {string} [className='ol-scale-line'] CSS Class name. * @property {number} [minWidth=64] Minimum width in pixels at the OGC default dpi. The width will be * adjusted to match the dpi used. - * @property {number|undefined} [maxWidth=undefined] Maximum width in pixels at the OGC default dpi. The width will be + * @property {number} [maxWidth] Maximum width in pixels at the OGC default dpi. The width will be * adjusted to match the dpi used. * @property {function(import("../MapEvent.js").default):void} [render] Function called when the control * should be re-rendered. This is called in a `requestAnimationFrame` callback. From 5742f0c06839d4c7fecc0da562933521702efbd1 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Fri, 1 Apr 2022 14:29:01 +0200 Subject: [PATCH 3/3] Add tests --- .../browser/spec/ol/control/scaleline.test.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/browser/spec/ol/control/scaleline.test.js b/test/browser/spec/ol/control/scaleline.test.js index 076f83ff36..85cdefc536 100644 --- a/test/browser/spec/ol/control/scaleline.test.js +++ b/test/browser/spec/ol/control/scaleline.test.js @@ -79,6 +79,19 @@ describe('ol.control.ScaleLine', function () { }); }); + describe('maxWidth', function () { + it('defaults to undefined', function () { + const ctrl = new ScaleLine(); + expect(ctrl.maxWidth_).to.be(undefined); + }); + it('can be configured', function () { + const ctrl = new ScaleLine({ + maxWidth: 4711, + }); + expect(ctrl.maxWidth_).to.be(4711); + }); + }); + describe('render', function () { it('defaults to `ol.control.ScaleLine.render`', function () { const ctrl = new ScaleLine(); @@ -325,6 +338,21 @@ describe('ol.control.ScaleLine', function () { expect(ctrl.element.innerText).to.be('100 km'); }); + it('maxWidth is applied correctly', function () { + const ctrl = new ScaleLine({maxWidth: 50}); + ctrl.setMap(map); + map.setView( + new View({ + center: fromLonLat([-85.685, 39.891], 'Indiana-East'), + zoom: 7, + projection: 'Indiana-East', + }) + ); + map.renderSync(); + // without maxWidth set this would be 100 km + expect(ctrl.element.innerText).to.be('50 km'); + }); + it('shows the same scale for different projections at higher resolutions', function () { const ctrl = new ScaleLine(); ctrl.setMap(map);