Skip to content

Commit

Permalink
Introducing ol.overlay.Overlay and an overlayContainer
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ahocevar committed Sep 28, 2012
1 parent a46e251 commit 3d62b67
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 22 deletions.
2 changes: 1 addition & 1 deletion css/ol.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.ol-viewport {
.ol-viewport .ol-unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
Expand Down
7 changes: 7 additions & 0 deletions demos/full-screen/full-screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');


Expand All @@ -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')
});
3 changes: 2 additions & 1 deletion src/ol/control/control.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};
5 changes: 1 addition & 4 deletions src/ol/control/zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
35 changes: 24 additions & 11 deletions src/ol/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -63,14 +64,6 @@ ol.MapProperty = {
};


/**
* @enum {number}
*/
ol.MapPaneZIndex = {
VIEWPORT: 1000
};



/**
* @constructor
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions src/ol/mapbrowserevent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};
Expand All @@ -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;
Expand Down
185 changes: 185 additions & 0 deletions src/ol/overlay/overlay.js
Original file line number Diff line number Diff line change
@@ -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'
};
4 changes: 2 additions & 2 deletions src/ol/renderer/dom/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
3 changes: 2 additions & 1 deletion src/ol/renderer/webgl/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3d62b67

Please sign in to comment.