Reputation: 17487
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
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
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
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
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
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
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
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
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
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
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
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
Reputation: 17487
Thanks to the example link provided by Azathoth in the comments I worked a solution out:
pointermove
eventHere 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