ProfNimrod
ProfNimrod

Reputation: 4310

Adding event handler to feature in OpenLayers 3?

I am using the following code to add a feature to a vector layer in OpenLayers 3 (OL3):

marker = new ol.Feature({
    geometry: new ol.geom.Point([longitude, latitude]),
    name: "Location Marker"
});
markerStyle = new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0.5, 1.0],
    anchorXUnits: "fraction",
    anchorYUnits: "fraction",
    src: "Content/Images/OpenLayers/marker_trans.png"
  }),
  zIndex: 100000
});
marker.setStyle(markerStyle);
marker.on("click", function(e) {
  // do something
}, marker);
map.getSource().addFeature(marker);

The marker displays as expected, but the click event never fires. What am I doing wrong?

I should note that there is already a handler associated with "click" at the map level, i.e.

map.on("click", function(e) {
  // do something
}, marker);

Upvotes: 16

Views: 52049

Answers (3)

Simon Zyx
Simon Zyx

Reputation: 7161

First: Features don't fire clicks! For information on the events features do fire, check http://openlayers.org/en/master/apidoc/ol.Feature.html.

For checking if a feature did get clicked, there is the .forEachFeatureAtPixel(pixel, callback) function of ol.Map. ( http://openlayers.org/en/master/apidoc/ol.Map.html#forEachFeatureAtPixel ) The callback is executed on every feature at the pixel. The callback gets passed 2 arguments: the feature and the layer the feature is in.

Good to know is the .getEventPixel(event) function, if you don't work with openlayers event handlers but with handlers on the viewport. If your using openlayers eventhandler, the event has a property .pixel. (http://openlayers.org/en/master/apidoc/ol.Map.html#getEventPixel) The methods .getEventCoordinate(event) and .getCoordinateFromPixels(pixels) might be useful, too.

So you would add it like this to your map.on("click", ... :

map.on("click", function(e) {
    map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
        //do something
    })
});

Same thing with jQuery:

$(map.getViewport()).on("click", function(e) {
    map.forEachFeatureAtPixel(map.getEventPixel(e), function (feature, layer) {
        //do something
    });
});

Same thing with pure JS:

map.getViewport().addEventListener("click", function(e) {
    map.forEachFeatureAtPixel(map.getEventPixel(e), function (feature, layer) {
        //do something
    });
});

You might also want to check this example, there are two uses of this function, first with openlayers events, the second with jQuery events: http://openlayers.org/en/master/examples/icon.js

Note

There is also the possibility to do this with an ol.interaction.Select (http://openlayers.org/en/master/apidoc/ol.interaction.Select.html?unstable=true), but this is a little bit overpowered for this case. And it has some unintuitive caveats caused by openlayers internally moving the selected features to another so called unmanaged layer.

Anyhow this works by adding a listener to the collection belonging to the interaction. The collection can be retrieved with .getFeatures().

interaction.getFeatures().on("add", function (e) { 
    // do something. e.element is the feature which was added
});

Upvotes: 53

Amir Dashti
Amir Dashti

Reputation: 369

If you just need to add a marker on your map which is clickable, you can use overlays. In your HTML header define your marker's style:

<style>
    #marker {
        width: 20px;
        height: 20px;
        border: 1px solid #088;
        border-radius: 10px;
        background-color: #0FF;
        opacity: 0.5;
    }
</style>

then in script part of your file, after the map is created:

    // add marker
    var pos = ol.proj.fromLonLat([0.01123, 0.00612]);
    var marker = new ol.Overlay({
        position: pos,
        positioning: 'center-center',
        element: $('<div id="marker" title="Marker"></div>')
            .popover({
                'placement': 'top',
                'html': true,
                'content': '<strong>anything...</strong>'
            })
            .on('click', function (e) { $(".location-popover").not(this).popover('hide'); }),
        stopEvent: false
    });
    map.addOverlay(marker);

Upvotes: 2

Costales
Costales

Reputation: 2873

If you just want a click on a map, this will work for you.

  var map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.MapQuest({layer: 'sat'})
      })
    ],
    view: new ol.View({
      center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
      zoom: 4
    })
  });

map.on("click", function(evt) {
    var coord = ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
    var lon = coord[0];
    var lat = coord[1];
    alert(lon);
    alert(lat);
});

Upvotes: 3

Related Questions