Pierre Henry
Pierre Henry

Reputation: 17487

How to change the cursor on hover in openlayers 3?

I managed to add interactivity to a feature layer added from a remote GeoJSON resource. When I click on a feature I get its ID, fire an AJAX request and display some relevant info about the feature, on the page outside of the map area.

I used a Select interaction.

I would like to make it even clearer to the user that he can click on the features on the map. Is there any way I can change the mouse cursor to "cursor" of "hand" when the mouse hovers a feature contained in a ol.layer.Vector ?

I couldn't find anything in the doc, on this site or by googling.

Upvotes: 26

Views: 37562

Answers (12)

Pablo
Pablo

Reputation: 1682

It can be done as well without jQuery:

map.on("pointermove", function (evt) {
    var hit = this.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
        return true;
    }); 
    if (hit) {
        this.getTargetElement().style.cursor = 'pointer';
    } else {
        this.getTargetElement().style.cursor = '';
    }
});

Upvotes: 34

Emin Adiloğlu
Emin Adiloğlu

Reputation: 97

Easy way

map.on('pointermove', (e) => {
      const pixel = map.getEventPixel(e.originalEvent);
      const hit = map.hasFeatureAtPixel(pixel);
      document.getElementById('map').style.cursor = hit ? 'pointer' : '';
    });
}

Upvotes: 0

AamirR
AamirR

Reputation: 12198

I tried to minimize pointermove event closure, by avoiding to update style when not necessary, because it calls so very often:

Example-1: uses jQuery:

var cursorStyle = "";
map.on("pointermove", function (e) {
    let newStyle = this.hasFeatureAtPixel(e.pixel) ? "pointer" : "";
    newStyle !== cursorStyle && $(this.getTargetElement()).css("cursor", cursorStyle = newStyle);
});

Example-2: no jQuery:

var cursorStyle = "";
map.on("pointermove", function (e) {
    let newStyle = this.hasFeatureAtPixel(e.pixel) ? "pointer" : "";
    if (newStyle !== cursorStyle) {
        this.getTargetElement().style.cursor = cursorStyle = newStyle;
    }
});

Upvotes: 0

Robert M
Robert M

Reputation: 235

Here is another way to do it:

map.on('pointermove', function(e){
  var pixel = map.getEventPixel(e.originalEvent);
  var hit = map.hasFeatureAtPixel(pixel);
  map.getViewport().style.cursor = hit ? 'pointer' : '';
});

Upvotes: 22

winnewoerp
winnewoerp

Reputation: 241

For me it worked like this:

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 true;
          });
          e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
        });

I also added a layer filter:

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 layer.get('name') === 'myLayer';
      });
      e.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
    });

I had to select a new solution as the old one I had use for the layer filter before did not work anymore:

var hit = e.map.hasFeatureAtPixel(e.pixel, function(layer){
             return layer.get('name') === 'myLayer';
          });

Upvotes: 4

ohjeeez
ohjeeez

Reputation: 557

If that doesn't work, try a combination of the 2, seemed to work for my vector popup...

var target = map.getTarget();
var jTarget = typeof target === "string" ? $("#" + target) : $(target);
// change mouse cursor when over marker
$(map.getViewport()).on('mousemove', function (e) {
    var pixel = map.getEventPixel(e.originalEvent);
    var hit = map.forEachFeatureAtPixel(pixel, function (feature, layer) {
        return true;
    });
    if (hit) {
        jTarget.css("cursor", "pointer");
    } else {
        jTarget.css("cursor", "");
    }
});

Upvotes: 13

nix86
nix86

Reputation: 3037

If you guys are using Angular 2 you must use the following code:

this.map.on("pointermove", function (evt) {
    var hit = evt.map.hasFeatureAtPixel(evt.pixel);
    this.getTargetElement().style.cursor = hit ? 'pointer' : '';
});

If the map variable is a member class you refer to it as "this.map", instead if it is declared inside the current function it can be refered to as "map". But above all, you don't write

map.getTargetElement()

but you write

this.getTargetElement()

Upvotes: 1

cinthyasm
cinthyasm

Reputation: 31

Uncaught TypeError: Cannot set property 'cursor' of undefined.

Fixed with: map.getTargetElement()s.style.cursor = hit ? 'pointer' : ''; instead of map.getTarget().style.cursor = hit ? 'pointer' : '';

Upvotes: 2

JustAC0der
JustAC0der

Reputation: 3157

Another way (combined from parts of above answers, but even simpler):

map.on("pointermove", function (evt) {
    var hit = map.hasFeatureAtPixel(evt.pixel);
    map.getTargetElement().style.cursor = (hit ? 'pointer' : '');
});

Upvotes: 4

Nurlan
Nurlan

Reputation: 803

Simple way to get target element

var target = map.getTarget();

target = typeof target === "string" ?
    document.getElementById(target) : target;

target.style.cursor = features.length > 0) ? 'pointer' : '';

Upvotes: 1

NoRyb
NoRyb

Reputation: 1544

I did it with the following code:

var target = $(map.getTargetElement()); //getTargetElement is experimental as of 01.10.2015
map.on('pointermove', function (evt) {
    if (map.hasFeatureAtPixel(evt.pixel)) { //hasFeatureAtPixel is experimental as of 01.10.2015
        target.css('cursor', 'pointer');
    } else {
        target.css('cursor', '');
    }
});

Upvotes: 2

Pierre Henry
Pierre Henry

Reputation: 17487

Thanks to the example link provided by Azathoth in the comments I worked a solution out:

  • using OL3 pointermove event
  • using jQuery to get the target element and change its cursor style

Here is the code :

var cursorHoverStyle = "pointer";
var target = map.getTarget();

//target returned might be the DOM element or the ID of this element dependeing on how the map was initialized
//either way get a jQuery object for it
var jTarget = typeof target === "string" ? $("#"+target) : $(target);

map.on("pointermove", function (event) {
    var mouseCoordInMapPixels = [event.originalEvent.offsetX, event.originalEvent.offsetY];

    //detect feature at mouse coords
    var hit = map.forEachFeatureAtPixel(mouseCoordInMapPixels, function (feature, layer) {
        return true;
    });

    if (hit) {
        jTarget.css("cursor", cursorHoverStyle);
    } else {
        jTarget.css("cursor", "");
    }
});

Here is the link to the example on OpenLayers site : http://openlayers.org/en/v3.0.0/examples/icon.html

Upvotes: 10

Related Questions