Marco Toniut
Marco Toniut

Reputation: 588

How do I change the default cursor in leaflet maps?

I am trying to modify the default cursor icon when a certain control button is pressed. Although I was partially successful by using css on the container div, doing this overrides the move cursor state, which is something I do not want. What I mean with this is that the move icon no longer appears while moving through the map (but not when on markers!).

I'd like to know if there is a non-hacky way through the api to achieve special cursor behaviour without redifining everything.

This is what I tried to do, #map is the container div for the leaflet map.

#map[control=pressed] {
    cursor: url('..custom.png');
}

Upvotes: 29

Views: 38041

Answers (9)

johannes
johannes

Reputation: 1448

The only thing that worker for me was this CSS:

.leaflet-interactive {
    cursor: crosshair;
}

Upvotes: 0

Serge Titov
Serge Titov

Reputation: 11

Add to your rule another selector, that wil also match .leaflet-interactive class

#map[control=pressed],
#map[control=pressed] .leaflet-interactive {
    cursor: url('..custom.png');
}

The root problem is with svg-based overlays, wich have inner elements with leaflet-interactive class like

<svg> <g> <path class="leaflet-interactive">...

And it turns out that leaflet's native style .leaflet-interactive { cursor: pointer; } has higher specifity inside svg, than even id-based rule from main document.

Upvotes: 0

Alexander van Oostenrijk
Alexander van Oostenrijk

Reputation: 4774

I use react-leaflet and needed to change the cursor over the map and the polygons on it, based on a bit of state higher up in the app. Changing the cursor for the map itself was simple:

map.getContainer().style.cursor = 'crosshair';

For the polygons on the map it was not as straightforward. Leaflet polygons take a className option, which could be used to override the default leaflet-interactive class that sets the cursor to pointer. However, I found that className was not a dynamic option: re-rendering the polygon did not change the className (see this github issue).

I use styled-components, so I tried to wrap the Polygon component to override the cursor style rule, but this, also, only worked when the Polygon was first created. Eventually, I settled on capturing a reference to the Polygon object:

<Polygon ref={(el:any) => this.wrapperRef = el} /* ... */ />

and used this to set the cursor style rule on update:

componentDidUpdate = () => {
  this.wrapperRef._path.style.cursor = this.props.cursor;
}

As discussed in the aforementioned github issue, the property _path of the object created by Leaflet can be used to access and override the style.

Upvotes: 2

saadat ali
saadat ali

Reputation: 1053

$('.leaflet-container').css('cursor','crosshair');

Upvotes: 1

cityremade
cityremade

Reputation: 31

This is what worked for me:

// CSS first. Add this to leaflet stylesheet.
.leaflet-interactive.wait-cursor-enabled {
    cursor: wait !important;
}

// JS select from map container and add class to each element
let map = L.map('map');
let els = map.getContainer().querySelectorAll('.leaflet-interactive');
for(let el of els){
   el.classList += ' wait-cursor-enabled'; 
}

//JS remove class once no longer needed
let els = map.getContainer().querySelectorAll('.leaflet-interactive.wait-cursor-enabled');
for(let el of els){
   el.classList.remove("wait-cursor-enabled");
}

Upvotes: 1

elrobis
elrobis

Reputation: 1562

Edit 5.18.2017: Raw CSS and Javascript via Leaflet Framework (recommended)

I was looking through the source code for the BoxZoom plugin and noticed their approach using Leaflet's built-in DOM mutators and wanted to promote it here...this is certainly the best practice.

Example jsfiddle

Somewhere in your CSS include a class like this..

.leaflet-container.crosshair-cursor-enabled {
    cursor:crosshair;
}

When you want to enable crosshairs, do this in your JS..

// Assumes your Leaflet map variable is 'map'..
L.DomUtil.addClass(map._container,'crosshair-cursor-enabled');

Then, when you want to disable crosshairs, do this in your JS..

L.DomUtil.removeClass(map._container,'crosshair-cursor-enabled');

Original Answer: Map-level Crosshairs

@scud42 got me on the right path. You can use JQuery to change the Leaflet map cursor like this:

$('.leaflet-container').css('cursor','crosshair');

Then later, when you want to reset the map cursor, you can do this:

$('.leaflet-container').css('cursor','');

Edit 1.21.2016: Per-feature Crosshairs

You can also enable crosshairs for individual features supporting the className option, such as a polygon, or feature vertices, etc.

Here's an example of a draggable vertice that will toggle pointer crosshairs (jsfiddle):

var svg_html_default = '<div style="margin:0px;padding:0px;height:8px;width:8px;border-style:solid;border-color:#FFFFFF;border-width:1px;background-color:#424242"</div>';

var default_icon = L.divIcon({
  html: svg_html_default,
  className: 'leaflet-mouse-marker',
  iconAnchor: [5,5],
  iconSize: [8,8]
});

var m = new L.marker([33.9731003, -80.9968865], {
  icon: default_icon,
  draggable: true,
  opacity: 0.7
}).addTo( map );

m.on("mouseover",function(){$('.leaflet-mouse-marker').css('cursor','crosshair');});

m.on("mouseout",function(){$('.leaflet-mouse-marker').css('cursor','');});

Upvotes: 56

chelahmy
chelahmy

Reputation: 124

Set to crosshair:

document.getElementById('map').style.cursor = 'crosshair'

Reset it back:

document.getElementById('map').style.cursor = ''

Upvotes: 6

scud42
scud42

Reputation: 121

Leaflet's styles allow you to change some cursor behavior. Put these in your local CSS to make the change.

/* Change cursor when mousing over clickable layer */
.leaflet-clickable {
  cursor: crosshair !important;
}
/* Change cursor when over entire map */
.leaflet-container {
  cursor: help !important;
}

Upvotes: 12

Austin Brunkhorst
Austin Brunkhorst

Reputation: 21130

Use the active pseudo class.

#map:active {
    cursor: url('..custom.png');
}

JSFiddle

For overriding a cursor you will probably want to use the css3 attribute user-select: none so that it doesn't toggle between the text and default cursor when dragging on the element. That implementation is also shown in the JSFiddle.

Upvotes: 2

Related Questions