From 61f49c276464974cb6aa5a1efe09932c2830909a Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Tue, 10 Sep 2019 18:50:54 +0100 Subject: [PATCH] Revise and correct OverviewMap rotation Correct the box display when the main map view is rotated and add an option to rotate either the box or the overview map view --- src/ol/control/OverviewMap.js | 112 +++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 42 deletions(-) diff --git a/src/ol/control/OverviewMap.js b/src/ol/control/OverviewMap.js index 2f59b39698..ed889c5717 100644 --- a/src/ol/control/OverviewMap.js +++ b/src/ol/control/OverviewMap.js @@ -11,12 +11,11 @@ import Overlay from '../Overlay.js'; import OverlayPositioning from '../OverlayPositioning.js'; import ViewProperty from '../ViewProperty.js'; import Control from './Control.js'; -import {rotate as rotateCoordinate, add as addCoordinate} from '../coordinate.js'; import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_COLLAPSED} from '../css.js'; import {replaceNode} from '../dom.js'; import {listen, listenOnce} from '../events.js'; import EventType from '../events/EventType.js'; -import {containsExtent, equals as equalsExtent, getBottomLeft, getBottomRight, getTopLeft, getTopRight, scaleFromCenter} from '../extent.js'; +import {containsExtent, equals as equalsExtent, getBottomRight, getTopLeft, scaleFromCenter} from '../extent.js'; /** @@ -55,6 +54,7 @@ class ControlledMap extends PluggableMap { * Layers for the overview map. * @property {function(import("../MapEvent.js").default)} [render] Function called when the control * should be re-rendered. This is called in a `requestAnimationFrame` callback. + * @property {boolean} [rotateWithView=false] Whether the control view should rotate with the main map view. * @property {HTMLElement|string} [target] Specify a target if you want the control * to be rendered outside of the map's viewport. * @property {string} [tipLabel='Overview map'] Text label to use for the button tip. @@ -64,7 +64,7 @@ class ControlledMap extends PluggableMap { /** - * Create a new control with a map acting as an overview map for an other + * Create a new control with a map acting as an overview map for another * defined map. * * @api @@ -106,6 +106,19 @@ class OverviewMap extends Control { this.collapsed_ = false; } + /** + * @private + * @type {boolean} + */ + this.rotateWithView_ = options.rotateWithView !== undefined ? + options.rotateWithView : false; + + /** + * @private + * @type {import("../extent.js").Extent|undefined} + */ + this.viewExtent_ = undefined; + const className = options.className !== undefined ? options.className : 'ol-overviewmap'; const tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Overview map'; @@ -178,7 +191,7 @@ class OverviewMap extends Control { */ this.boxOverlay_ = new Overlay({ position: [0, 0], - positioning: OverlayPositioning.BOTTOM_LEFT, + positioning: OverlayPositioning.CENTER_CENTER, element: box }); this.ovmap_.addOverlay(this.boxOverlay_); @@ -303,12 +316,12 @@ class OverviewMap extends Control { /** * Handle rotation changes to the main map. - * TODO: This should rotate the extent rectangle instead of the - * overview map's view. * @private */ handleRotationChanged_() { - this.ovmap_.getView().setRotation(this.getMap().getView().getRotation()); + if (this.rotateWithView_) { + this.ovmap_.getView().setRotation(this.getMap().getView().getRotation()); + } } /** @@ -431,51 +444,30 @@ class OverviewMap extends Control { const ovview = ovmap.getView(); - const rotation = view.getRotation(); + const rotation = this.rotateWithView_ ? 0 : -view.getRotation(); const overlay = this.boxOverlay_; const box = this.boxOverlay_.getElement(); - const extent = view.calculateExtent(mapSize); + const center = view.getCenter(); + const resolution = view.getResolution(); const ovresolution = ovview.getResolution(); - const bottomLeft = getBottomLeft(extent); - const topRight = getTopRight(extent); + const width = mapSize[0] * resolution / ovresolution; + const height = mapSize[1] * resolution / ovresolution; - // set position using bottom left coordinates - const rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft); - overlay.setPosition(rotateBottomLeft); + // set position using center coordinates + overlay.setPosition(center); // set box size calculated from map extent size and overview map resolution if (box) { - box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px'; - box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px'; + box.style.width = width + 'px'; + box.style.height = height + 'px'; + const transform = 'rotate(' + rotation + 'rad)'; + box.style.msTransform = transform; + box.style.webkitTransform = transform; + box.style.transform = transform; } } - /** - * @param {number} rotation Target rotation. - * @param {import("../coordinate.js").Coordinate} coordinate Coordinate. - * @return {import("../coordinate.js").Coordinate|undefined} Coordinate for rotation and center anchor. - * @private - */ - calculateCoordinateRotate_(rotation, coordinate) { - let coordinateRotate; - - const map = this.getMap(); - const view = map.getView(); - - const currentCenter = view.getCenter(); - - if (currentCenter) { - coordinateRotate = [ - coordinate[0] - currentCenter[0], - coordinate[1] - currentCenter[1] - ]; - rotateCoordinate(coordinateRotate, rotation); - addCoordinate(coordinateRotate, currentCenter); - } - return coordinateRotate; - } - /** * @param {MouseEvent} event The event to handle * @private @@ -500,7 +492,12 @@ class OverviewMap extends Control { // manage overview map if it had not been rendered before and control // is expanded const ovmap = this.ovmap_; - if (!this.collapsed_ && !ovmap.isRendered()) { + if (!this.collapsed_) { + if (ovmap.isRendered()) { + this.viewExtent_ = undefined; + ovmap.render(); + return; + } ovmap.updateSize(); this.resetExtent_(); listenOnce(ovmap, MapEventType.POSTRENDER, @@ -559,6 +556,37 @@ class OverviewMap extends Control { return this.collapsed_; } + /** + * Return `true` if the overview map view can rotate, `false` otherwise. + * @return {boolean} True if the control view can rotate. + * @api + */ + getRotateWithView() { + return this.rotateWithView_; + } + + /** + * Set whether the overview map view should rotate with the main map view. + * @param {boolean} rotateWithView True if the control view should rotate. + * @api + */ + setRotateWithView(rotateWithView) { + if (this.rotateWithView_ === rotateWithView) { + return; + } + this.rotateWithView_ = rotateWithView; + if (this.getMap().getView().getRotation() !== 0) { + if (this.rotateWithView_) { + this.handleRotationChanged_(); + } else { + this.ovmap_.getView().setRotation(0); + } + this.viewExtent_ = undefined; + this.validateExtent_(); + this.updateBox_(); + } + } + /** * Return the overview map. * @return {import("../PluggableMap.js").default} Overview map.