How to change the cursor on hover in openlayers 3?
Asked Answered
S

12

25

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.

Stylist answered 24/9, 2014 at 16:31 Comment(5)
There is an example: openlayers.org/en/v3.0.0/examples/icon.html. To be honest I'm trying to use the same method in my map but without success: Uncaught TypeError: Cannot set property 'cursor' of undefinedAlbertalberta
@Albertalberta getTarget gives you what to give to the map target: either string or HTMLElement. Should be HTMLElement, like in the example, if you want to change its style.Heterogony
@Heterogony I think I copied all the code usend in the example but console.log(map.getTarget()); prints a string containing "map"Albertalberta
@Albertalberta : see my answer on how to deal with the string value you getStylist
map.getTargetElement().style.cursor = 'pointer'; worked for meRegulation
G
33

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 = '';
    }
});
Guillermo answered 9/12, 2014 at 21:17 Comment(1)
In 3.17.1 this code works. But not with this.getTarget(), use this.getTargetElement()Wesson
S
20

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' : '';
});
Shang answered 2/2, 2016 at 17:57 Comment(1)
Side note, you should add the missing paren ");" at the end for easy copy pastingFinzer
B
13

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", "");
    }
});
Brussels answered 15/12, 2014 at 23:15 Comment(1)
this one works for me, the others don't. OL3 // Version: v3.1.0-pre.2-179-gca3dfe2Subminiaturize
S
10

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

Stylist answered 26/9, 2014 at 13:54 Comment(0)
N
4

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' : '');
});
Nutbrown answered 21/3, 2016 at 13:59 Comment(1)
This is the correct way to fo it with OpenLayers 5.Convenience
J
4

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';
          });
Jovita answered 26/1, 2017 at 11:4 Comment(1)
Interesting idea, but don't forget to mention that a layer has no native 'name' attribution, and this has to be set (here, on layer creation). var myLayer = new ol.layer.Vector({ source: mySource, style: myStyle, name: "myLayerName" });Cinder
T
2

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', '');
    }
});
Theatricals answered 1/10, 2015 at 8:57 Comment(0)
W
2

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' : '';

Wilhelminawilhelmine answered 12/4, 2016 at 21:7 Comment(0)
V
1

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' : '';
Verecund answered 24/12, 2015 at 10:6 Comment(1)
Reason for downvote: use map.getTargetElement() (openlayers.org/en/latest/apidoc/ol.Map.html#getTargetElement).Rms
I
1

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()
Iain answered 27/5, 2016 at 15:13 Comment(0)
T
0

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;
    }
});
Trophy answered 26/12, 2018 at 19:57 Comment(0)
F
0

Easy way

map.on('pointermove', (e) => {
      const pixel = map.getEventPixel(e.originalEvent);
      const hit = map.hasFeatureAtPixel(pixel);
      document.getElementById('map').style.cursor = hit ? 'pointer' : '';
    });
}
Foliolate answered 18/6, 2019 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.