2

I have a leaflet map. I'm using circles for markers because I have some zooming built in, and I want the radius of the circles to animate during the zoom. I also, though, want the circles to "pulse" if they're clicked. I see a lot of documentation for pulsing leaflet markers online, but none for pulsing circles. Is there a simple solution here?

jquery:

var map = L.map('map').setView([40.449620, -79.939990], 13);

L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}{r}.{ext}', {
    maxZoom: 19,
    ext: 'png',
    attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'//,
}).addTo(map);

map.on('click', function(e) {
    var currentZoom = map.getZoom();
    if (currentZoom == 13) {
        map.flyTo(e.latlng, 15, { //zoom in on click
                animate: true,
                duration: 1,
                easeLinearity: 1
        });
    }
});
$.post('php/get-buildings.php', function(output){
    var obj = jQuery.parseJSON( output );

    var color;

    customCircle = L.Circle.extend({
       options: { 
          //some more options here
       }
    });

     for (var i=0; i<obj.length; i++) {

        if (obj[i].there_2017 == 'No') {
            color = '#000';
        } else {
            color = '#1565C0';
        }
        //var circle = L.circle([obj[i].lat,obj[i].lng], {
        var circle = new customCircle([obj[i].lat,obj[i].lng], {
            color: '#000',
            weight: 0.5,
            fillColor: color,
            fillOpacity: 1,
            borderWidth: 2,
            radius: 40,
            //some more properties
        }).addTo(map).on("click", circleClick);

        function circleClick(e) {
          var clickedCircle = e.target;
          clickedCircle.setStyle({'weight': '3'});  want to animate this
        }

    }//end for
});
LauraNMS
  • 2,720
  • 7
  • 39
  • 73

1 Answers1

7

A solution to have a pulsating circle marker is to use a divIcon and create a pulsating marker you like with css.

js code :

    const generatePulsatingMarker = function (radius, color) {
      const cssStyle = `
        width: ${radius}px;
        height: ${radius}px;
        background: ${color};
        color: ${color};
        box-shadow: 0 0 0 ${color};
      `
      return L.divIcon({
        html: `<span style="${cssStyle}" class="pulse"/>`,
        // empty class name to prevent the default leaflet-div-icon to apply
        className: ''
      })
    }
    
    const pulsatingIcon = generatePulsatingMarker(10, 'red');
    L.marker([51.497, -0.09], {icon: pulsatingIcon}).addTo(map);

and the CSS pulsating marker :

    .pulse {
      display: block;
      border-radius: 50%;
      cursor: pointer;
      animation: pulse 2s infinite;
    }
    
    @keyframes pulse {
      0% {
        -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.4);
        box-shadow: 0 0 0 0;
      }
      70% {
        -moz-box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);
         box-shadow: 0 0 0 10px rgba(0, 0, 0, 0);
      }
      100% {
        -moz-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
         box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
      }
    }

example fiddle here

Also, if you want the marker to pulse only when clicked, then add the corresponding "pulse" css class on click event.

Istopopoki
  • 1,584
  • 1
  • 13
  • 20
  • #Istopopoki: Almost there! The pulsating divIcon has a white background instead of a transparent one. It isn't that way on your fiddle, but I don't see what I'm doing wrong. function markerClick(e) { var clickedMarker = e.target; var pulsatingIcon = generatePulsatingMarker(10, '#f49934'); L.marker([clickedMarker._latlng.lat, clickedMarker._latlng.lng], {icon: pulsatingIcon}).addTo(map); } – LauraNMS Jan 18 '19 at 16:02
  • const generatePulsatingMarker = function (radius, color) { const margin = 0 const cssStyle = `margin-left:-${margin}px; margin-top:-${margin}px; width: ${radius}px; height: ${radius}px; background: ${color}; color: ${color}; box-shadow: 0 0 0 ${color}; ` return L.divIcon({ html: ``, }) } – LauraNMS Jan 18 '19 at 16:02
  • I fixed it: In the const declaration: return L.divIcon({ className: 'dummy', html: `` – LauraNMS Jan 18 '19 at 16:16