2

I have a map on which one layer overlays the other one (I have icon markers displayed and larger circles markers behind them). I'm trying to create a function that changes the icon symbol AND the circle symbology while hovering over a feature. I need both icon and circle markers to appear at the same time, when the mouse gets over the icon.

What's happening so far is that I can't display the updated icon and circle together, I have to slightly hover on the sides to display the icon (as in the images, red cross is my cursor). What is my mistake ?

Circle updated Icon updated

Here is my code :

//Initial circle symbology - circles are invisible
var buffer_zone = L.geoJSON(studios, {
    onEachFeature: mouse_events_buffer,
    pointToLayer: function (zone, coord){
    var circlebuff = new L.circle(coord, 100, {color : '#006080', fillColor : '#99ccff', fillOpacity : 0, opacity : 0, weight : 1});
    return circlebuff;
    }
}).addTo(map);

//Initial icon style
var studioicon = L.icon({
    iconUrl: 'cinema.png',
    iconSize: [40, 40],
    iconAnchor: [15,15]
  });
      
//Icon marker and icon style that should appear when hovering
var studios_marker = L.geoJSON(studios, {
onEachFeature: mouse_events_studios,
pointToLayer: function (feature, latlng){
    var smallIcon = L.icon({
    iconUrl: ''+ feature.properties.Name +'.png',
    iconSize: [80, 60],
    iconAnchor: [15,15]
    });
    var marker = L.marker(latlng, {icon: studioicon});
    marker.smallIcon = smallIcon;
    return marker;
}
}).addTo(map);


function mouse_events_buffer(feature, buff){

//Change circle style (ie add color and bigger radius)
    buff.on('mouseover', function(buffer_on){
        var obj_buffer1 = buffer_on.target;
        buff.setStyle({color : '#006080', fillColor : '#99ccff', 
        fillOpacity : 0.3, opacity : 1, weight : 1});
        buff.setRadius(3000)
    });

//Set the original style back
    buff.on('mouseout', function(buffer_off){
        var obj_buffer2 = buffer_off.target;
        buffer_zone.resetStyle(buffer_off.target);
    });
}
  
function mouse_events_studios(feature, marker){

//Change icon style (different png and size)
    marker.on('mouseover', function(alter_style){
        var leaflet_obj2 = alter_style.target;
        marker.setIcon(marker.smallIcon);
    });

//Set the original style back
    marker.on('mouseout', function(origin_style){
        var leaflet_obj3 = origin_style.target;
        marker.setIcon(studioicon);
    });

//Additionnal action (this works)
    marker.on('mouseover', function(resume){
        var leaflet_obj4 = resume.target;
        var info1 = document.getElementById("studio_name");
        info1.innerHTML = leaflet_obj4.feature.properties.Name
        var info2 = document.getElementById("studio_resume");
        info2.innerHTML = leaflet_obj4.feature.properties.resume
    })
}
4
  • From your description, combined with your code, it's not exactly clear what you want to achieve. For example, initial buffer_zone circles are transparent. Are they used only for mouse over detection? Please edit your question with more detailed step by step description of the behavior: initial state, mouse over buffer, mouse over icon.
    – TomazicM
    Dec 16, 2021 at 9:52
  • @TomazicM Yes, they're transparent and I want them to "appear" (ie be colored) only when the cursor is over each feature. I'll edit my post.
    – cam_gis
    Dec 16, 2021 at 10:00
  • But should buffer be visible also when the mouse gets over icon in the center of the buffer? Please add also that info.
    – TomazicM
    Dec 16, 2021 at 10:02
  • Yes, that's precisely what I need. Buffer and icon should appear together at the same time, but they don't.
    – cam_gis
    Dec 16, 2021 at 10:05

1 Answer 1

2

Event mouseout gets fired when mouse leaves feature/element or when it enters another feature/HTML element, even when the second feature/element is inside area of the first feature/element. That's the reason why buffer zone circle feature gets hidden when mouse enters studio marker, which lies inside buffer zone circle.

HTML DOM model has also mouseleave event, which gets fired only when mouse goes outside area of an HTML element, but unluckily Leaflet does not treat this event separately from mouseout event.

One possible solution in your case would be to check distance from circle center when mouseout event is fired. Circle can then be hidden only when distance is bigger that circle radius.

There is also no need to have two GeoJSON layers, one for markers and other for buffers. It all can be done with a single layer and only pointToLayer option function.

Code could then look something like this:

var radiusTransparent = 100;
var radiusVisible = 3000;

var studioicon = L.icon({
  iconUrl: 'cinema.png',
  iconSize: [40, 40],
  iconAnchor: [15,15]
});
  
function setBufferVisible(buffer, setVisible) {
  if (setVisible) {
    buffer.setStyle(visibleBufferStyle);
    buffer.setRadius(radiusVisible);
    }
  else {
    buffer.setStyle(transparentBufferStyle);
    buffer.setRadius(radiusTransparent);
  }
}

function showStudioInfo(name, resume) {
  var info1 = document.getElementById("studio_name");
  info1.innerHTML = name;
  var info2 = document.getElementById("studio_resume");
  info2.innerHTML = resume;
}

var visibleBuffer = null;
var studios_marker = L.geoJSON(studios, {
  pointToLayer: function (feature, latlng){
    var smallIcon = L.icon({
      iconUrl: ''+ feature.properties.Name +'.png',
      iconSize: [80, 60],
      iconAnchor: [15,15]
    });
    var marker = L.marker(latlng, {icon: studioicon});
    marker.smallIcon = smallIcon;
    marker.feature = feature;
    marker.on('mouseover', function(evt) {
      marker.setIcon(marker.smallIcon);
      var properties = marker.feature.properties;
      showStudioInfo(properties.Name, properties.resume);
    });
    marker.on('mouseout', function(evt){
      marker.setIcon(studioicon);
      showStudioInfo('', '');
    });

    var buffer = new L.circle(latlng, radiusTransparent, transparentBufferStyle);
    buffer.on('mouseover', function(evt){
      if (visibleBuffer) {
        setBufferVisible(visibleBuffer, false);
      }
      setBufferVisible(buffer, true);
      visibleBuffer = buffer;
    });
    buffer.on('mouseout', function(evt){
      var distance = map.distance(evt.latlng, latlng);
      if (distance > radiusVisible) {
        setBufferVisible(buffer, false);
      }
    });
    
    var markerGroup = L.layerGroup([buffer, marker]);
    return markerGroup;
  }
}).addTo(map);
3
  • Thank you very much!! It works perfectly. However, with this solution, my text that was displayed with "innerHTML" doesn't appear anymore...
    – cam_gis
    Dec 17, 2021 at 12:33
  • 1
    You are right, in pointToLayer function feature is not available by default in marker events, so it has to be added manually. See corrected answer.
    – TomazicM
    Dec 17, 2021 at 15:00
  • All good now. A million thanks for the help!
    – cam_gis
    Dec 17, 2021 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.