2

I am using the function to define popup contents in a map, and right now, it createa a popup for every feature I click on the map, no matter what layer it is in. I would like this popup to appear only for features within one layer. I'm sure there is a way I can specify this in the function, but I'm not sure how. I tried using this for line 6 if (feature && layer === layerVector) { but it gave me an error saying that layer is undefined. layerVector is the variable name for the layer I want to use the popup for. Can anyone help? Here is the code:

map.on('click', function(evt) {
  var feature = map.forEachFeatureAtPixel(evt.pixel,
      function(feature, layer) {
        return feature;
      });
  if (feature) {
    popup.setPosition(evt.coordinate);
      content.innerHTML = '<b>Parcel No: </b>'+
      feature.get('parcel')+'<br>'+
      '<b>Owner: </b>'+
      feature.get('primowner')
  } 
});

2 Answers 2

8

When doing forEachFeatureAtPixel, you should do any filtrering inside the callback function. You have the feature and it's layer available as arguments.

This would return the first clicked feature:

var feature = map.forEachFeatureAtPixel(pixel,
  function(feature, layer) {
    return feature;
  }
);

This would return the first clicked feature in targetLayer:

var feature = map.forEachFeatureAtPixel(pixel,
  function(feature, layer) {
    if (layer == targetLayer) {
      return feature;
    }
  }
);

But when you know that you are only interested in a set of specific layers, a simple optimization is to use the fourth argument: the layer filter function.

The layer filter function is called once for each vector layer, and determines if the layer should be used when looking for features at the given pixel. The code above would trigger an unnecessary spatial lookup in all vector layers, while the code below will only look for matching features in targetLayer:

var feature = map.forEachFeatureAtPixel(pixel,
  function (feature, layer) {
    return feature;
  },
  this, // third argument, determines 'this' for the callback
  function (layer) {
    return layer == targetLayer;
  }
);
1
  • Thanks so much for the reply, that works perfectly. I don't quite understand how tthe last bit of code that you posted works though
    – kflaw
    Commented Oct 22, 2015 at 14:47
0

just return an object holding feature and layer and not only feature. Then access the layer through object. something like that:

map.on('click', function (evt) {
    var obj = map.forEachFeatureAtPixel(evt.pixel,

    function (feature, layer) {
        return [feature,layer];
    });
    console.log(obj)
    if (obj) {
        console.info("layer is",obj[1]);
        var feature =obj[0];
        var layer= obj[1];
        if(layer === featureOverlay){
        alert("yes is my layer!!!");
        popup.setPosition(evt.coordinate);
        //$(container).popover({
        //'placement': 'top',
        //'html': true,
        content.innerHTML = '<b>Parcel No: </b>' + feature.get('parcel') + '<br>' +
            '<b>Owner: </b>' + feature.get('primowner')
        }  
    }
});
11
  • Thanks for the answer! I tried to use this code, but I don't understand what it's telling me in the console. It seems to work in firefox, but in chrome the popup does not appear. In firefox, when it does return the popup, it's very slow now. Also with firefox, the popup doesn't show the first couple of times I click on features where it should show.
    – kflaw
    Commented Oct 21, 2015 at 20:54
  • Its your code but I just return [fetaure, layer] instead of feature only. console info returns the layer object, dont expect to get the layer name or a human readable string. If you set an attribute like "NAME" when initialising the layer then you may get it back like so layer.get('NAME'). The slowness is strange as returning just one more object can not make the browser getting slow. Check your code or provide a fiddle to enlighten us
    – pavlos
    Commented Oct 21, 2015 at 21:11
  • Here is a link to a fiddle, I did not include your code. But you can see what else is in there. I am thinking that maybe what might be best is to add the geolocFeature as an overlay rather than load it into a vector layer. jsfiddle.net/kflaw/yasL746r
    – kflaw
    Commented Oct 21, 2015 at 21:20
  • Ok I tried that and it didn't change the behavior.
    – kflaw
    Commented Oct 21, 2015 at 21:27
  • Ok I managed to make the fiddle working. So where are the parcels??? I mean in which area I may find parcels??? You need to check whether click is taking place on geoloc or parcels. right????? and if on parcel popup else not popup. right?????
    – pavlos
    Commented Oct 21, 2015 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.