diff --git a/examples/vector-layer.js b/examples/vector-layer.js index 1f23f67028..c15023685a 100644 --- a/examples/vector-layer.js +++ b/examples/vector-layer.js @@ -42,6 +42,15 @@ var map = new ol.Map({ }) }); +map.on('mousemove', function(evt) { + var features = map.getFeatureInfoForPixel(evt.getPixel(), [vector]); + var info = []; + for (var i = 0, ii = features.length; i < ii; ++i) { + info.push(features[i].get('name')); + } + document.getElementById('map').title = info.join(', '); +}); + var geojson = new ol.parser.GeoJSON(); var url = 'data/countries.json'; diff --git a/src/ol/map.exports b/src/ol/map.exports index 6fa9bba48a..048d03366d 100644 --- a/src/ol/map.exports +++ b/src/ol/map.exports @@ -2,6 +2,7 @@ @exportProperty ol.Map.prototype.addLayer @exportProperty ol.Map.prototype.addPreRenderFunction @exportProperty ol.Map.prototype.addPreRenderFunctions +@exportProperty ol.Map.prototype.getFeatureInfoForPixel @exportProperty ol.Map.prototype.getInteractions @exportProperty ol.Map.prototype.getRenderer @exportProperty ol.Map.prototype.removeLayer diff --git a/src/ol/map.js b/src/ol/map.js index 616ed73c0c..7da8568ae2 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -427,6 +427,34 @@ ol.Map.prototype.getCoordinateFromPixel = function(pixel) { }; +/** + * Get feature information for a pixel on the map. + * + * @param {ol.Pixel} pixel Pixel coordinate relative to the map viewport. + * @param {Array.|undefined} opt_layers Layers to restrict the + * query to. All layers will be queried if not provided. + * @return {Array.} Feature information. Layers that are + * able to return attribute data will return ol.Feature instances, other + * layers will return a string which can either be plain text or markup. + */ +ol.Map.prototype.getFeatureInfoForPixel = function(pixel, opt_layers) { + var renderer = this.getRenderer(); + var layers = goog.isDefAndNotNull(opt_layers) ? + opt_layers : this.getLayers().getArray(); + var layer, layerRenderer; + var featureInfo = []; + for (var i = 0, ii = layers.length; i < ii; ++i) { + layer = layers[i]; + layerRenderer = renderer.getLayerRenderer(layer); + if (goog.isFunction(layerRenderer.getFeatureInfoForPixel)) { + featureInfo.push.apply(featureInfo, + layerRenderer.getFeatureInfoForPixel(pixel)); + } + } + return featureInfo; +}; + + /** * @return {ol.Collection} Interactions. */ diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 108458b198..4e7c982f26 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -147,6 +147,12 @@ ol.MapBrowserEventHandler = function(map) { */ this.downListenerKey_ = null; + /** + * @type {?number} + * @private + */ + this.moveListenerKey_ = null; + /** * @type {Array.} * @private @@ -172,6 +178,9 @@ ol.MapBrowserEventHandler = function(map) { this.downListenerKey_ = goog.events.listen(element, goog.events.EventType.MOUSEDOWN, this.handleMouseDown_, false, this); + this.moveListenerKey_ = goog.events.listen(element, + goog.events.EventType.MOUSEMOVE, + this.relayMouseMove_, false, this); // touch events this.touchListenerKeys_ = [ goog.events.listen(element, [ @@ -281,6 +290,19 @@ ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) { }; +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @private + */ +ol.MapBrowserEventHandler.prototype.relayMouseMove_ = function(browserEvent) { + if (goog.events.hasListener( + this.map_, ol.MapBrowserEvent.EventType.MOUSEMOVE)) { + this.dispatchEvent(new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.MOUSEMOVE, this.map_, browserEvent)); + } +}; + + /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @private @@ -335,6 +357,7 @@ ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) { ol.MapBrowserEventHandler.prototype.disposeInternal = function() { goog.events.unlistenByKey(this.clickListenerKey_); goog.events.unlistenByKey(this.downListenerKey_); + goog.events.unlistenByKey(this.moveListenerKey_); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; @@ -360,5 +383,6 @@ ol.MapBrowserEvent.EventType = { DRAGEND: 'dragend', TOUCHSTART: goog.events.EventType.TOUCHSTART, TOUCHMOVE: goog.events.EventType.TOUCHMOVE, - TOUCHEND: goog.events.EventType.TOUCHEND + TOUCHEND: goog.events.EventType.TOUCHEND, + MOUSEMOVE: goog.events.EventType.MOUSEMOVE }; diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index b343880a36..266815fb22 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -187,6 +187,26 @@ ol.renderer.canvas.VectorLayer.prototype.getTransform = function() { }; +/** + * @param {ol.Pixel} pixel Pixel coordinate relative to the map viewport. + * @return {Array.} Features at the pixel location. + */ +ol.renderer.canvas.VectorLayer.prototype.getFeatureInfoForPixel = + function(pixel) { + // TODO adjust pixel tolerance for point features + var minPixel = new ol.Pixel(pixel.x - 1, pixel.y - 1); + var maxPixel = new ol.Pixel(pixel.x + 1, pixel.y + 1); + var map = this.getMap(); + var minCoordinate = map.getCoordinateFromPixel(minPixel); + var maxCoordinate = map.getCoordinateFromPixel(maxPixel); + var bbox = ol.extent.boundingExtent([minCoordinate, maxCoordinate]); + var filter = new ol.filter.Extent(bbox); + + // TODO do a real intersect against the filtered result for exact matches + return this.getLayer().getFeatures(filter); +}; + + /** * @param {goog.events.Event} event Layer change event. * @private