Add autoPan option to ol.Overlay

This commit is contained in:
tsauerwein
2015-02-19 17:41:09 +01:00
parent eb1a46cf7d
commit e46e0f85fb
4 changed files with 181 additions and 5 deletions

View File

@@ -298,3 +298,35 @@ ol.dom.transformElement2D =
// content size.
}
};
/**
* Get the current computed width for the given element including margin,
* padding and border.
* Equivalent to jQuery's `$(el).outerWidth(true)`.
* @param {!Element} element Element.
* @return {number}
*/
ol.dom.outerWidth = function(element) {
var width = element.offsetWidth;
var style = element.currentStyle || window.getComputedStyle(element);
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
return width;
};
/**
* Get the current computed height for the given element including margin,
* padding and border.
* Equivalent to jQuery's `$(el).outerHeight(true)`.
* @param {!Element} element Element.
* @return {number}
*/
ol.dom.outerHeight = function(element) {
var height = element.offsetHeight;
var style = element.currentStyle || window.getComputedStyle(element);
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
return height;
};

View File

@@ -11,6 +11,9 @@ goog.require('ol.Coordinate');
goog.require('ol.Map');
goog.require('ol.MapEventType');
goog.require('ol.Object');
goog.require('ol.animation');
goog.require('ol.dom');
goog.require('ol.extent');
/**
@@ -90,6 +93,26 @@ ol.Overlay = function(options) {
this.element_ = goog.dom.createElement(goog.dom.TagName.DIV);
this.element_.style.position = 'absolute';
/**
* @private
* @type {boolean}
*/
this.autoPan_ = goog.isDef(options.autoPan) ? options.autoPan : true;
/**
* @private
* @type {olx.animation.PanOptions}
*/
this.autoPanAnimation_ = goog.isDef(options.autoPanAnimation) ?
options.autoPanAnimation : /** @type {olx.animation.PanOptions} */ ({});
/**
* @private
* @type {number}
*/
this.autoPanMargin_ = goog.isDef(options.autoPanMargin) ?
options.autoPanMargin : 20;
/**
* @private
* @type {{bottom_: string,
@@ -291,6 +314,9 @@ ol.Overlay.prototype.handleOffsetChanged = function() {
*/
ol.Overlay.prototype.handlePositionChanged = function() {
this.updatePixelPosition_();
if (goog.isDef(this.get(ol.OverlayProperty.POSITION)) && this.autoPan_) {
this.panIntoView_();
}
};
@@ -364,6 +390,89 @@ goog.exportProperty(
ol.Overlay.prototype.setPosition);
/**
* Pan the map so that the overlay is entirely visible in the current viewport
* (if necessary).
* @private
*/
ol.Overlay.prototype.panIntoView_ = function() {
goog.asserts.assert(this.autoPan_);
var map = this.getMap();
if (!goog.isDef(map) || goog.isNull(map.getTargetElement())) {
return;
}
var mapRect = this.getRect_(map.getTargetElement(), map.getSize());
var element = this.getElement();
goog.asserts.assert(!goog.isNull(element) && goog.isDef(element));
var overlayRect = this.getRect_(element,
[ol.dom.outerWidth(element), ol.dom.outerHeight(element)]);
var margin = this.autoPanMargin_;
if (!ol.extent.containsExtent(mapRect, overlayRect)) {
// the overlay is not completely inside the viewport, so pan the map
var offsetLeft = overlayRect[0] - mapRect[0];
var offsetRight = mapRect[2] - overlayRect[2];
var offsetTop = overlayRect[1] - mapRect[1];
var offsetBottom = mapRect[3] - overlayRect[3];
var delta = [0, 0];
if (offsetLeft < 0) {
// move map to the left
delta[0] = offsetLeft - margin;
} else if (offsetRight < 0) {
// move map to the right
delta[0] = Math.abs(offsetRight) + margin;
}
if (offsetTop < 0) {
// move map up
delta[1] = offsetTop - margin;
} else if (offsetBottom < 0) {
// move map down
delta[1] = Math.abs(offsetBottom) + margin;
}
if (delta[0] !== 0 || delta[1] !== 0) {
var center = map.getView().getCenter();
goog.asserts.assert(goog.isDef(center));
var centerPx = map.getPixelFromCoordinate(center);
var newCenterPx = [
centerPx[0] + delta[0],
centerPx[1] + delta[1]
];
if (!goog.isNull(this.autoPanAnimation_)) {
this.autoPanAnimation_.source = center;
map.beforeRender(ol.animation.pan(this.autoPanAnimation_));
}
map.getView().setCenter(map.getCoordinateFromPixel(newCenterPx));
}
}
};
/**
* Get the extent of an element relative to the document
* @param {Element|undefined} element The element.
* @param {ol.Size|undefined} size The size of the element.
* @return {ol.Extent}
* @private
*/
ol.Overlay.prototype.getRect_ = function(element, size) {
goog.asserts.assert(!goog.isNull(element) && goog.isDef(element));
goog.asserts.assert(goog.isDef(size));
var offset = goog.style.getPageOffset(element);
return [
offset.x,
offset.y,
offset.x + size[0],
offset.y + size[1]
];
};
/**
* Set the positioning for this overlay.
* @param {ol.OverlayPositioning} positioning how the overlay is