Merge pull request #10800 from ejn/overlay-pan-into-view-10741

Make Overlay.panIntoView an API method
This commit is contained in:
Andreas Hocevar
2020-03-31 23:19:38 +02:00
committed by GitHub

View File

@@ -37,15 +37,21 @@ import {containsExtent} from './extent.js';
* container as that of the controls (see the `stopEvent` option) you will * container as that of the controls (see the `stopEvent` option) you will
* probably set `insertFirst` to `true` so the overlay is displayed below the * probably set `insertFirst` to `true` so the overlay is displayed below the
* controls. * controls.
* @property {boolean} [autoPan=false] If set to `true` the map is panned when * @property {PanIntoViewOptions|boolean} [autoPan=false] Pan the map when calling
* calling `setPosition`, so that the overlay is entirely visible in the current * `setPosition`, so that the overlay is entirely visible in the current viewport?
* viewport. * If `true` (deprecated), then `autoPanAnimation` and `autoPanMargin` will be
* @property {PanOptions} [autoPanAnimation] The * used to determine the panning parameters; if an object is supplied then other
* animation options used to pan the overlay into view. This animation is only * parameters are ignored.
* used when `autoPan` is enabled. A `duration` and `easing` may be provided to * @property {PanOptions} [autoPanAnimation] The animation options used to pan
* customize the animation. * the overlay into view. This animation is only used when `autoPan` is enabled.
* A `duration` and `easing` may be provided to customize the animation.
* Deprecated and ignored if `autoPan` is supplied as an object.
* @property {number} [autoPanMargin=20] The margin (in pixels) between the * @property {number} [autoPanMargin=20] The margin (in pixels) between the
* overlay and the borders of the map when autopanning. * overlay and the borders of the map when autopanning. Deprecated and ignored
* if `autoPan` is supplied as an object.
* @property {PanIntoViewOptions} [autoPanOptions] The options to use for the
* autoPan. This is only used when `autoPan` is enabled and has preference over
* the individual `autoPanMargin` and `autoPanOptions`.
* @property {string} [className='ol-overlay-container ol-selectable'] CSS class * @property {string} [className='ol-overlay-container ol-selectable'] CSS class
* name. * name.
*/ */
@@ -60,6 +66,12 @@ import {containsExtent} from './extent.js';
* Default is {@link module:ol/easing~inAndOut}. * Default is {@link module:ol/easing~inAndOut}.
*/ */
/**
* @typedef {Object} PanIntoViewOptions
* @property {PanOptions} [animation={}] The animation parameters for the pan
* @property {number} [margin=20] The margin (in pixels) between the
* overlay and the borders of the map when panning into view.
*/
/** /**
* @enum {string} * @enum {string}
@@ -137,24 +149,18 @@ class Overlay extends BaseObject {
options.className : 'ol-overlay-container ' + CLASS_SELECTABLE; options.className : 'ol-overlay-container ' + CLASS_SELECTABLE;
this.element.style.position = 'absolute'; this.element.style.position = 'absolute';
let autoPan = options.autoPan;
if (autoPan && ('object' !== typeof autoPan)) {
autoPan = {
animation: options.autoPanAnimation,
margin: options.autoPanMargin
};
}
/** /**
* @protected * @protected
* @type {boolean} * @type {PanIntoViewOptions|false}
*/ */
this.autoPan = options.autoPan !== undefined ? options.autoPan : false; this.autoPan = /** @type {PanIntoViewOptions} */(autoPan) || false;
/**
* @protected
* @type {PanOptions}
*/
this.autoPanAnimation = options.autoPanAnimation || /** @type {PanOptions} */ ({});
/**
* @protected
* @type {number}
*/
this.autoPanMargin = options.autoPanMargin !== undefined ?
options.autoPanMargin : 20;
/** /**
* @protected * @protected
@@ -316,9 +322,7 @@ class Overlay extends BaseObject {
*/ */
handlePositionChanged() { handlePositionChanged() {
this.updatePixelPosition(); this.updatePixelPosition();
if (this.get(Property.POSITION) && this.autoPan) { this.performAutoPan();
this.panIntoView();
}
} }
/** /**
@@ -372,14 +376,26 @@ class Overlay extends BaseObject {
} }
/** /**
* Pan the map so that the overlay is entirely visible in the current viewport * Pan the map so that the overlay is entirely visisble in the current viewport
* (if necessary). * (if necessary) using the configured autoPan parameters
* @protected * @protected
*/ */
panIntoView() { performAutoPan() {
if (this.autoPan) {
this.panIntoView(this.autoPan);
}
}
/**
* Pan the map so that the overlay is entirely visible in the current viewport
* (if necessary).
* @param {PanIntoViewOptions|undefined} panIntoViewOptions Options for the pan action
* @api
*/
panIntoView(panIntoViewOptions) {
const map = this.getMap(); const map = this.getMap();
if (!map || !map.getTargetElement()) { if (!map || !map.getTargetElement() || !this.get(Property.POSITION)) {
return; return;
} }
@@ -387,7 +403,7 @@ class Overlay extends BaseObject {
const element = this.getElement(); const element = this.getElement();
const overlayRect = this.getRect(element, [outerWidth(element), outerHeight(element)]); const overlayRect = this.getRect(element, [outerWidth(element), outerHeight(element)]);
const margin = this.autoPanMargin; const myMargin = (panIntoViewOptions.margin === undefined) ? 20 : panIntoViewOptions.margin;
if (!containsExtent(mapRect, overlayRect)) { if (!containsExtent(mapRect, overlayRect)) {
// the overlay is not completely inside the viewport, so pan the map // the overlay is not completely inside the viewport, so pan the map
const offsetLeft = overlayRect[0] - mapRect[0]; const offsetLeft = overlayRect[0] - mapRect[0];
@@ -398,17 +414,17 @@ class Overlay extends BaseObject {
const delta = [0, 0]; const delta = [0, 0];
if (offsetLeft < 0) { if (offsetLeft < 0) {
// move map to the left // move map to the left
delta[0] = offsetLeft - margin; delta[0] = offsetLeft - myMargin;
} else if (offsetRight < 0) { } else if (offsetRight < 0) {
// move map to the right // move map to the right
delta[0] = Math.abs(offsetRight) + margin; delta[0] = Math.abs(offsetRight) + myMargin;
} }
if (offsetTop < 0) { if (offsetTop < 0) {
// move map up // move map up
delta[1] = offsetTop - margin; delta[1] = offsetTop - myMargin;
} else if (offsetBottom < 0) { } else if (offsetBottom < 0) {
// move map down // move map down
delta[1] = Math.abs(offsetBottom) + margin; delta[1] = Math.abs(offsetBottom) + myMargin;
} }
if (delta[0] !== 0 || delta[1] !== 0) { if (delta[0] !== 0 || delta[1] !== 0) {
@@ -419,10 +435,11 @@ class Overlay extends BaseObject {
centerPx[1] + delta[1] centerPx[1] + delta[1]
]; ];
const panOptions = panIntoViewOptions.animation || {};
map.getView().animateInternal({ map.getView().animateInternal({
center: map.getCoordinateFromPixelInternal(newCenterPx), center: map.getCoordinateFromPixelInternal(newCenterPx),
duration: this.autoPanAnimation.duration, duration: panOptions.duration,
easing: this.autoPanAnimation.easing easing: panOptions.easing
}); });
} }
} }