Introducing ol.overlay.Overlay and an overlayContainer
ol.overlay.Overlay can be used to bind DOM elements to a coordinate on the map. It has positioning options to support e.g. popups or image markers that have an anchor at the bottom and an unknown size. The overlayContainer stops propagation on mousedown and touchstart events, so clicks and gestures on overlays don't trigger any MapBrowserEvent. To make this work reliably, we now only fire dblclick in mapbrowserevent.js when there was a previous mousedown or touchstart. The default container for controls is now the overlayContainer.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
.ol-viewport {
|
||||
.ol-viewport .ol-unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
|
||||
@@ -5,6 +5,7 @@ goog.require('ol.Collection');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapOptions'); // FIXME this should not be required
|
||||
goog.require('ol.overlay.Overlay');
|
||||
goog.require('ol.source.MapQuestOpenAerial');
|
||||
|
||||
|
||||
@@ -22,3 +23,9 @@ var map = new ol.Map(document.getElementById('map'), {
|
||||
layers: new ol.Collection([layer]),
|
||||
zoom: 2
|
||||
});
|
||||
var vienna = new ol.overlay.Overlay({
|
||||
map: map,
|
||||
coordinate: ol.Projection.transformWithCodes(
|
||||
new ol.Coordinate(16, 48), 'EPSG:4326', 'EPSG:3857'),
|
||||
element: document.getElementById('vienna')
|
||||
});
|
||||
|
||||
@@ -67,7 +67,8 @@ ol.control.Control.prototype.setMap = function(map) {
|
||||
}
|
||||
this.map_ = map;
|
||||
if (!goog.isNull(this.map_)) {
|
||||
var target = goog.isDef(this.target_) ? this.target_ : map.getViewport();
|
||||
var target = goog.isDef(this.target_) ?
|
||||
this.target_ : map.getOverlayContainer();
|
||||
goog.dom.appendChild(target, this.element);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,10 +42,7 @@ ol.control.Zoom = function(zoomOptions) {
|
||||
goog.events.listen(outElement, eventType, this.handleOut_, false, this);
|
||||
|
||||
var element = goog.dom.createDom(
|
||||
goog.dom.TagName.DIV, 'ol-zoom', inElement, outElement);
|
||||
goog.events.listen(
|
||||
element, ol.BrowserFeature.HAS_TOUCH ? goog.events.EventType.TOUCHSTART :
|
||||
goog.events.EventType.MOUSEDOWN, goog.events.Event.stopPropagation);
|
||||
goog.dom.TagName.DIV, 'ol-zoom ol-unselectable', inElement, outElement);
|
||||
|
||||
goog.base(this, {
|
||||
element: element,
|
||||
|
||||
@@ -24,6 +24,7 @@ goog.require('goog.functions');
|
||||
goog.require('goog.fx.anim');
|
||||
goog.require('goog.fx.anim.Animated');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.BrowserFeature');
|
||||
goog.require('ol.Collection');
|
||||
goog.require('ol.Color');
|
||||
goog.require('ol.Constraints');
|
||||
@@ -63,14 +64,6 @@ ol.MapProperty = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ol.MapPaneZIndex = {
|
||||
VIEWPORT: 1000
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
@@ -145,15 +138,25 @@ ol.Map = function(container, mapOptionsLiteral) {
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.viewport_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.viewport_.className = 'ol-viewport';
|
||||
this.viewport_ = goog.dom.createDom(goog.dom.TagName.DIV, 'ol-viewport');
|
||||
this.viewport_.style.position = 'relative';
|
||||
this.viewport_.style.overflow = 'hidden';
|
||||
this.viewport_.style.width = '100%';
|
||||
this.viewport_.style.height = '100%';
|
||||
this.viewport_.style.zIndex = ol.MapPaneZIndex.VIEWPORT;
|
||||
goog.dom.appendChild(container, this.viewport_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.overlayContainer_ = goog.dom.createDom(goog.dom.TagName.DIV,
|
||||
'ol-overlaycontainer');
|
||||
goog.events.listen(this.overlayContainer_,
|
||||
ol.BrowserFeature.HAS_TOUCH ?
|
||||
goog.events.EventType.TOUCHSTART : goog.events.EventType.MOUSEDOWN,
|
||||
goog.events.Event.stopPropagation);
|
||||
goog.dom.appendChild(this.viewport_, this.overlayContainer_);
|
||||
|
||||
var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this);
|
||||
goog.events.listen(mapBrowserEventHandler, [
|
||||
ol.MapBrowserEvent.EventType.CLICK,
|
||||
@@ -504,6 +507,16 @@ ol.Map.prototype.getViewport = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} The map's overlay container. Elements added to this
|
||||
* container won't let mousedown and touchstart events through to the map, so
|
||||
* clicks and gestures on an overlay don't trigger any MapBrowserEvent.
|
||||
*/
|
||||
ol.Map.prototype.getOverlayContainer = function() {
|
||||
return this.overlayContainer_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} browserEvent Browser event.
|
||||
* @param {string=} opt_type Type.
|
||||
|
||||
@@ -170,7 +170,6 @@ ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) {
|
||||
this.touchEnableBrowserEvent_(browserEvent);
|
||||
var newEvent = new ol.MapBrowserEvent(
|
||||
ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent);
|
||||
this.down_ = null;
|
||||
this.dispatchEvent(newEvent);
|
||||
}
|
||||
};
|
||||
@@ -181,7 +180,7 @@ ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) {
|
||||
* @private
|
||||
*/
|
||||
ol.MapBrowserEventHandler.prototype.dblclick_ = function(browserEvent) {
|
||||
if (!this.dragged_) {
|
||||
if (!this.dragged_ && this.down_) {
|
||||
var now = new Date().getTime();
|
||||
if (!this.timestamp_ || now - this.timestamp_ > 250) {
|
||||
this.timestamp_ = now;
|
||||
|
||||
185
src/ol/overlay/overlay.js
Normal file
185
src/ol/overlay/overlay.js
Normal file
@@ -0,0 +1,185 @@
|
||||
goog.provide('ol.overlay.Overlay');
|
||||
goog.provide('ol.overlay.OverlayOptions');
|
||||
goog.provide('ol.overlay.OverlayPositioning');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.MapProperty');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{coordinate: (ol.Coordinate|undefined),
|
||||
* element: (Element|undefined),
|
||||
* map: (ol.Map|undefined),
|
||||
* positioning: (Array.<string>|undefined)}}
|
||||
*/
|
||||
ol.overlay.OverlayOptions;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {ol.overlay.OverlayOptions} overlayOptions Overlay options.
|
||||
*/
|
||||
ol.overlay.Overlay = function(overlayOptions) {
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.coordinate_ = null;
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
this.element_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @type {Array.<string>}
|
||||
* @private
|
||||
*/
|
||||
this.positioning_ = [
|
||||
ol.overlay.OverlayPositioning.LEFT,
|
||||
ol.overlay.OverlayPositioning.BOTTOM
|
||||
];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.mapListenerKeys_ = [];
|
||||
|
||||
if (goog.isDef(overlayOptions.coordinate)) {
|
||||
this.setCoordinate(overlayOptions.coordinate);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.element)) {
|
||||
this.setElement(overlayOptions.element);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.map)) {
|
||||
this.setMap(overlayOptions.map);
|
||||
}
|
||||
if (goog.isDef(overlayOptions.positioning)) {
|
||||
this.setPositioning(overlayOptions.positioning);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate for the overlay's position on
|
||||
* the map.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setCoordinate = function(coordinate) {
|
||||
this.coordinate_ = coordinate;
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} element The DOM element for the overlay.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setElement = function(element) {
|
||||
if (this.element_) {
|
||||
goog.dom.removeNode(this.element_);
|
||||
}
|
||||
this.element_ = element;
|
||||
if (this.map_) {
|
||||
goog.dom.append(/** @type {!Node} */ (this.map_.getOverlayContainer()),
|
||||
this.element_);
|
||||
}
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Element} The DOM element for the overlay.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.getElement = function() {
|
||||
return this.element_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Map} map Map.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setMap = function(map) {
|
||||
this.map_ = map;
|
||||
goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
|
||||
if (this.element_) {
|
||||
this.setElement(this.element_);
|
||||
}
|
||||
this.mapListenerKeys_ = map ? [
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.CENTER),
|
||||
this.updatePixelPosition_, false, this),
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION),
|
||||
this.updatePixelPosition_, false, this),
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.ROTATION),
|
||||
this.updatePixelPosition_, false, this),
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
|
||||
this.updatePixelPosition_, false, this)
|
||||
] : [];
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Map} Map.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.getMap = function() {
|
||||
return this.map_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the CSS properties to use for x- and y-positioning of the element. If
|
||||
* not set, the default is {@code ['left', 'bottom']}.
|
||||
* @param {Array.<string>} positioning The positioning.
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.setPositioning = function(positioning) {
|
||||
this.positioning_ = positioning;
|
||||
this.updatePixelPosition_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.overlay.Overlay.prototype.updatePixelPosition_ = function() {
|
||||
if (!goog.isNull(this.map_) && !goog.isNull(this.coordinate_) &&
|
||||
!goog.isNull(this.element_)) {
|
||||
var pixel = this.map_.getPixelFromCoordinate(this.coordinate_);
|
||||
var mapSize = this.map_.get(ol.MapProperty.SIZE);
|
||||
var x = Math.round(pixel.x);
|
||||
if (this.positioning_[0] === ol.overlay.OverlayPositioning.RIGHT) {
|
||||
x = mapSize.width - x;
|
||||
}
|
||||
var y = Math.round(pixel.y);
|
||||
if (this.positioning_[1] === ol.overlay.OverlayPositioning.BOTTOM) {
|
||||
y = mapSize.height - y;
|
||||
}
|
||||
goog.style.setStyle(this.element_, this.positioning_[0], x + 'px');
|
||||
goog.style.setStyle(this.element_, this.positioning_[1], y + 'px');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.overlay.OverlayPositioning = {
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
TOP: 'top',
|
||||
BOTTOM: 'bottom'
|
||||
};
|
||||
@@ -30,13 +30,13 @@ ol.renderer.dom.Map = function(container, map) {
|
||||
* @private
|
||||
*/
|
||||
this.layersPane_ = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.layersPane_.className = 'ol-layers-pane';
|
||||
this.layersPane_.className = 'ol-layers-pane ol-unselectable';
|
||||
var style = this.layersPane_.style;
|
||||
style.position = 'absolute';
|
||||
style.width = '100%';
|
||||
style.height = '100%';
|
||||
|
||||
goog.dom.appendChild(container, this.layersPane_);
|
||||
goog.dom.insertChildAt(container, this.layersPane_, 0);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
|
||||
@@ -151,7 +151,8 @@ ol.renderer.webgl.Map = function(container, map) {
|
||||
this.canvas_ = goog.dom.createElement(goog.dom.TagName.CANVAS);
|
||||
this.canvas_.height = container.clientHeight;
|
||||
this.canvas_.width = container.clientWidth;
|
||||
goog.dom.appendChild(container, this.canvas_);
|
||||
this.canvas_.className = 'ol-unselectable';
|
||||
goog.dom.insertChildAt(container, this.canvas_, 0);
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
||||
Reference in New Issue
Block a user