Merge pull request #9919 from mike-000/patch-2

Revise and correct OverviewMap rotation
This commit is contained in:
Tim Schaub
2019-09-11 17:38:53 -06:00
committed by GitHub
2 changed files with 79 additions and 45 deletions

View File

@@ -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.

View File

@@ -39,7 +39,9 @@ describe('ol.control.OverviewMap', function() {
});
map.setView(view);
const control = new OverviewMap();
const control = new OverviewMap({
rotateWithView: true
});
map.addControl(control);
const ovView = control.ovmap_.getView();
expect(ovView.getRotation()).to.be(0);
@@ -49,7 +51,9 @@ describe('ol.control.OverviewMap', function() {
});
it('maintains rotation in sync if view added later', function() {
const control = new OverviewMap();
const control = new OverviewMap({
rotateWithView: true
});
map.addControl(control);
const ovView = control.ovmap_.getView();
expect(ovView.getRotation()).to.be(0);
@@ -65,7 +69,9 @@ describe('ol.control.OverviewMap', function() {
});
it('stops listening to old maps', function() {
const control = new OverviewMap();
const control = new OverviewMap({
rotateWithView: true
});
const ovView = control.ovmap_.getView();
const view = new View({