TransWikia.com

Using circleMarker with mouseOver in Leaflet

Geographic Information Systems Asked by stgarcia on January 7, 2021

I am working from the example at
Highlighting feature by Id with Leaflet.

I wanted to change the appearance of the point layer by using circleMarkers, but now the script (who was supposed to highlight the corresponding setor polygon by mouseover on the commercial layer) doesn’t work anymore. I just added the pointToLayer function in "var commercial" and a style "setCircleMarker":

        <script type="text/javascript">
                    //initialisation de la carte
                    var map = L.map('mapid').setView([49.4, 1.3], 8);
                //fond de carte Mapbox
                L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
                    attribution: 'Map data &copy; <a href="https://www.mapbox.com/">Mapbox</a>',
                    maxZoom: 18,
                    id: 'mapbox/streets-v11',
                    tileSize: 512,
                    zoomOffset: -1,
                    accessToken: 'mypk'
                }).addTo(map);
                //style par défaut des secteurs
                var myStyle = {
                    "color": "#bb7800",
                    "weight": 5,
                    "opacity": 0.65
                };
                var setCircleMarker = {
                    radius: 7,
                    fillColor: "#1e7ead",
                    color: "white",
                    weight: 3,
                    opacity: 0.5,
                    fillOpacity: 1
                };  
                var json_commercial = {
                    "type": "FeatureCollection",
                    "name": "commercial",
                    "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
                    "features": [
                    { "type": "Feature", "properties": { "id": "1" }, "geometry": { "type": "Point", "coordinates": [ 1.305263516194724, 49.42360636638827 ] } },
                    { "type": "Feature", "properties": { "id": "2" }, "geometry": { "type": "Point", "coordinates": [ 1.974762218487792, 49.283373530097158 ] } }
                    ]
                }

                var json_secteurs = {
                    "type": "FeatureCollection",
                    "name": "secteurs",
                    "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
                    "features": [
                    { "type": "Feature", "properties": { "id": "1" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 1.020274203732134, 49.305991729498949 ], [ 1.309787156075082, 49.56836284255975 ], [ 1.789292983393091, 49.455271845550783 ], [ 1.020274203732134, 49.305991729498949 ] ] ] ] } },
                    { "type": "Feature", "properties": { "id": "2" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 1.789292983393091, 49.455271845550783 ], [ 1.309787156075082, 49.56836284255975 ], [ 1.775722063752015, 49.65883564016692 ], [ 1.789292983393091, 49.455271845550783 ] ] ] ] } },
                    { "type": "Feature", "properties": { "id": "3" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 1.789292983393091, 49.455271845550783 ], [ 1.775722063752015, 49.65883564016692 ], [ 2.318558849395044, 49.305991729498949 ], [ 1.689772906025202, 49.002907857514927 ], [ 1.789292983393091, 49.455271845550783 ] ] ] ] } },
                    { "type": "Feature", "properties": { "id": "4" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 1.789292983393091, 49.455271845550783 ], [ 1.689772906025202, 49.002907857514927 ], [ 1.020274203732134, 49.305991729498949 ], [ 1.789292983393091, 49.455271845550783 ] ] ] ] } }
                    ]
                }
                var featureLayers = new Array();
                var selectedLayer;

                function storeFeatureLayer(feature, layer) {
                    featureLayers[parseInt(feature.properties.id)] = layer;
                }

                function highlightSecteur(e) {
                    selectedLayer = featureLayers[parseInt(e.layer.feature.properties.id)];
                    selectedLayer.setStyle({color: '#ffff00'});
                }

                function resetStyle() {
                    selectedLayer.setStyle({color: "#bb7800"});
                }

                var commercial = L.geoJSON(json_commercial, {
                    style: myStyle,
                    pointToLayer: function (feature, latlng) {
                        return L.circleMarker(latlng, setCircleMarker);
                    }
                }).addTo(map);

                var secteur = L.geoJSON(json_secteurs, {
                    style: myStyle,
                    onEachFeature: storeFeatureLayer
                }).addTo(map);

                commercial.on('mouseover',highlightSecteur);
                commercial.on('mouseout',resetStyle);

        </script>

One Answer

Very interesting problem, hard to find the reason for this behaviour at the first sight.

Leaflet controls vertical ordering of layers on the map (what is above and what below) through placing them on so called map panes, which are separate div elements, each with it's own Z-index.

GeoJSON layer elements/features are placed on overlayPane whith Z-index value of 400. L.marker markers are placed on markerPane with Z-index value of 600, so markers are always above features.

Unlike L.marker markers, L.circleMarker markers are considered as vector overlay and as such placed on the same map pane as features, which is overlayPane. In this case vertical order of elements on the map depends on order of adding elements to the map: what comes later is above previously added layers/features.

In your case layer secteur is added after layer commercial and so polygons cover circle markers and as a consequence circle markers do not receive mouse events.

The simplest solution to this is to reverse the order of GeoJSON layers definition:

var secteur = L.geoJSON(json_secteurs, {
  style: myStyle,
  onEachFeature: storeFeatureLayer
}).addTo(map);

var commercial = L.geoJSON(json_commercial, {
  style: myStyle,
  pointToLayer: function (feature, latlng) {
    return L.circleMarker(latlng, setCircleMarker);
  }
}).addTo(map);

Second possibility would be to assign circle marker to markerPane, which can be done in marker definition options:

var setCircleMarker = {
  radius: 7,
  fillColor: "#1e7ead",
  color: "white",
  weight: 3,
  opacity: 0.5,
  fillOpacity: 1,
  pane: 'markerPane'
};  

Third possibility would be to have separate style for secteur layer and make it non interactive, so mouse events can go through it to circle markers:

var myStyle2 = {
  "color": "#bb7800",
  "weight": 5,
  "opacity": 0.65,
  "interactive": false
};

var secteur = L.geoJSON(json_secteurs, {
  style: myStyle2,
  onEachFeature: storeFeatureLayer
}).addTo(map);

Correct answer by TomazicM on January 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP