Svinjica
Svinjica

Reputation: 2519

Changing cursor style on pointermove for specified layer

quick (and I believe for some of you an easy) question regarding cursor styling while hovering above geojson layer/s.

So, I have one clip layer that I'm using to create a mask around wms layers, and another one that represents some administrative areas. As you can see in picture below enter image description here

What I would like is to change style of cursor when I'm hovering above administrative areas but it seems that I'm missing something.

I'm trying to isolate to layer only administrative borders layer using this block of code:

map.on('pointermove', function(e) {
if (e.dragging) return;
var pixel = e.map.getEventPixel(e.originalEvent);
var hit = e.map.forEachFeatureAtPixel(pixel, function(feature, layer) {
    return vectorJLS.get('layer_name') === 'jls';
});
   e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});

UPDATE

While JGH tweak code a bit it still doesn't work. I've detected that problem lies in layer that I'm using for mask clipping, when removed, code that JGH provided, works.

Here is code that I'm using for mask clipping

 var clipLayer = new ol.layer.Image({
     source: new ol.source.ImageVector({
         source: new ol.source.Vector({
             url: 'geojson/clip_wgs.geojson',
             format: new ol.format.GeoJSON()
         }),
         style: new ol.style.Style({
             fill: new ol.style.Fill({
                 color: 'black'
             })
         })
     })
 });


clipLayer.on('postcompose', function(e) {
    e.context.globalCompositeOperation = 'source-over';
});
clipLayer.on('precompose', function(e) {
    e.context.globalCompositeOperation = 'destination-in';
});
clipLayer.setMap(map);

Is it possible to somehow ignore clip layer when changing cursor style or should I take another approach?

UPDATE - 2

I've tweaked code a bit, but still without any success while clipedLayer is on.

map.on('pointermove', function(e) {
    if (e.dragging) return;

    var pixel = e.map.getEventPixel(e.originalEvent);
    // initialize the hit variable to false (not found)

    var hit = map.hasFeatureAtPixel(e.pixel, {
        layerFilter: function(layer) {
            return vectorJLS.get('layer_name') === 'jls';
        }
    });

    console.log(hit)
});

Interesting problem if I might add

Upvotes: 1

Views: 3158

Answers (2)

Svinjica
Svinjica

Reputation: 2519

Finally, with help from fellow JGH I've found appropriate solution for my problem. Searching release pages and google machine I've stumbled upon some interesting information regarding layer filters and its usage in method hasFeatureAtPixel. This block of code is valid for versions below 3.20.1 but more about that on OpenLayers Git

map.on('pointermove', function(e) {
    if (e.dragging) return;
    var pixel = e.map.getEventPixel(e.originalEvent);
    var hit = map.hasFeatureAtPixel(e.pixel, {
        layerFilter: function(layer) {
            return layer.get('layer_name') === 'jls';
        }
    });
     e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});

For newer versions you should use layer filter like this (I'm using 4.6.5)

map.hasFeatureAtPixel(pixel, {
  layerFilter: layerFilterFn.bind(layerFilterThis)
});

Or for my particular problem like this

map.on('pointermove', function(e) {
    if (e.dragging) return;
    var pixel = e.map.getEventPixel(e.originalEvent);
    var hit = map.hasFeatureAtPixel(e.pixel, {
        layerFilter: function(layer) {
            return layer.get('layer_name') === 'jls';
        }
    });
     e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});

Hope it helps :)

Upvotes: 3

JGH
JGH

Reputation: 17846

In your function, you are basically looping through all the layers at the mouse location. In that loop, if the layer has the proper name you set the pointer, else if it has a different name, you remove the pointer (or set it to something else).

As it is, it is dependent on the layer order:
ex: layer 1 = target -> set custom pointer. Layer 2 = other layer -> remove pointer. ==> final pointer: removed

ex: Layer 1 = other layer -> remove pointer. Layer 2 = target -> set custom pointer. ==> final pointer: custom pointer

The looping occurs when you set the hit variable, i.e. it corresponds to the last layer only as you are overriding the value for each layer.

map.on('pointermove', function(e) {
  if (e.dragging) return;

  var pixel = e.map.getEventPixel(e.originalEvent);
  // initialize the hit variable to false (not found)
  var hit = false;
  e.map.forEachFeatureAtPixel(pixel, function(feature, layer) {
    if ( vectorJLS.get('layer_name') === 'jls') {
          //IF we have found the layer, flag it (but don't return anything!)
          hit = true;
     }
  });

  e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});

Upvotes: 2

Related Questions