1

I would like the markers on my leaflet map to bounce when hover over corresponding list-item in sidebar. How to connect markers and list-items. List-items and popups all generated dynamically, their properties all stored in the same geoJSON file.

`
     var redFlag = L.icon({
     iconUrl: 'images/mapmarker2.png',
     iconSize: [34, 34],
     iconAnchor: [17,34]
    });

    const myLayer = L.geoJSON(art, {
        pointToLayer: function (feature, latlng) {

            for (var i = 0; i < art.features.length; i++) {
                var myMarker =  L.marker(latlng, {icon: redFlag})

            .setBouncingOptions({
                bounceHeight : 30,       
                bounceSpeed  : 54,       
                exclusive    : true, }) 

            .on('click', function() {
                this.bounce(3);          
            });

            feature.marker = myMarker;
            return myMarker;
       }  
},
  onEachFeature: function ( feature, layer) {
    layer.on('click', function(e){      
      const element = document.getElementById('popup');
      element.innerHTML =
        `<div class= "wrapper" style="background-color:#fff">`+
        `<div class="close">X</div>`+ 
        `<div class="popUpContent" style="background-color:#e8f4ff">` +
        `<div class='pic'><img src="images/${feature.properties.image}"> 
         </div><p>`+ 
        `<div class="puName">${feature.properties.name}</div>`+
        `<div class="puTitle">"${feature.properties.title}"</div><p>` + 
        `<div class="extra3">${feature.properties.extra}</div>`+ 
        `</div></div>`;  
      if (!feature.properties.title){    
        element.innerHTML = 
          `<div class= "wrapper" style="background-color:#fff">`+
          `<div class="close">X</div>`+ 
          `<div class="popUpContent" style="background-color:#e8f4ff">` +
          `<div class='pic'><img src="images/${feature.properties.image}"></div> 
           <p>`+ 
          `<div class="puName">${feature.properties.name}</div><p>`+
          `<div class="extra3">${feature.properties.extra}</div>`+ 
          `</div></div>`;           
      }
      if (!feature.properties.extra){   
        element.innerHTML = 
          `<div class= "wrapper" style="background-color:#fff">`+
          `<div class="close">X</div>`+ 
          `<div class="popUpContent" style="background-color:#e8f4ff">` +
          `<div class='pic'><img src="images/${feature.properties.image}"> 
           </div><p>`+ 
          `<div class="puName">${feature.properties.name}</div><p>`+ 
          `<div class="puTitle">"${feature.properties.title}"</div><p>` + 
          `</div></div>`;  
      }         
      document.getElementById('popup').addEventListener( 'click', closePopup);
      function closePopup(e){
        if (document.querySelector('.wrapper').style.display = 'block'){
          document.querySelector('.wrapper').style.display='none';
        }      
      }       
    });
  }
});

mymap.addLayer(myLayer);

function sortJson() {
  var name = [];
  for( const el of art.features){
    name.push(el);  
  }
  return name;
}

var artName = sortJson();
console.log(artName);

myArt = artName.sort((a,b)=> {
  var x = a.properties.name.toLowerCase();
  var y = b.properties.name.toLowerCase();
  return x < y ? -1 : x > y ? 1 : 0;
})

console.log(myArt)


// Add items and build list

var i = 1;
const buildItemList = (data) =>  {
  for ( const el of data) {
    var prop = el.properties;
    var myMarker = el.marker;

    var listings = document.getElementById('listings');
    var listing = listings.appendChild(document.createElement('div'));
    listing.className = 'item';
    listing.id = 'newItem_' + i++;
    listing.marker = myMarker;

    var content = document.createElement('div');
    listing.appendChild(content);
    content.className = 'content';
    content.innerHTML= `<div class="space">${prop.name}</div>`+ 
                      `<span class="info">'Title: "${prop.title}"</span> 
                       <br>` +
                      `<span class="extra">${prop.extra}<br>Adress: 
                      ${prop.adress}</span><br></div>`;

    if (!prop.extra){
      content.innerHTML = `<div class="space">${prop.name}</div>`+ 
        `<span class="info">'Title: "${prop.title}"</span><br>` +
        `<span class="extra" style="color:#fff">Adress: ${prop.adress} 
         </span></div>`;
    }

    if (!prop.title){
        content.innerHTML = `<div class="space">${prop.name}</div>`+ 
        `<span class="info"></span>` +
        `<span class="extra2">${prop.extra}<br>Adress: ${prop.adress}</span> 
        <div>`;
    }

  }                    
}

buildItemList(myArt);
1

Since you need acces to feature marker to bounce it, the simplest way to achieve this is to add marker as feature property upon marker creation:

  pointToLayer: function (feature, latlng) {
    var myMarker = L.marker(latlng, {icon: redFlag});
    feature.marker = myMarker;
    return myMarker;  
  },

Now when building your item list you can access marker through el.marker property and then add it as list div element property so it can be accessible when processing mouseover event for list item:

  for ( const el of data) {
    var prop = el.properties;
    var myMarker = el.marker;
    ...
    listing.marker = myMarker;
    ...

Four mouse bounce you can use Leaflet.SmoothMarkerBouncing plugin.

Below is simple tested example. Base of the code was taken from Leaflet GeoJSON example.

<!DOCTYPE html>
<html>

<head>
<title>GeoJSON tutorial - Leaflet</title>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<link href="docs/images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link crossorigin="" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" rel="stylesheet" />
<script crossorigin="" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<script src="../lib/Leaflet.SmoothMarkerBouncing/leaflet.smoothmarkerbouncing.js"></script>
<style>
    html, body {
      height: 100%;
      padding: 0;
      margin: 0;
    }       
    #map {
      width: 100%;
      height: 100%;
    }
    .myMenu {
      position: absolute;
      top: 10px;
      left: 10px;
      z-index: 1000;
      background-color: white; 
      padding: 4px;
      cursor: pointer;
  }
}
</style>
</head>

<body>

<div id="map"></div>
<div class="myMenu">
<div id="item1" onmouseover="shakeMarker(this)">Item 1</div>
<div id="item2" onmouseover="shakeMarker(this)">Item 2</div>
<div id="item3" onmouseover="shakeMarker(this)">Item 3</div>
<div id="item4" onmouseover="shakeMarker(this)">Item 4</div>
<div id="item5" onmouseover="shakeMarker(this)">Item 5</div>
<div id="item6" onmouseover="shakeMarker(this)">Item 6</div>
</div>

<script src="sample-geojson.js" type="text/javascript"></script>

<script>
  function shakeMarker(element) {
    element.marker.bounce(1);
  };

    var map = L.map('map', {zoomControl: false}).setView([39.74739, -105], 15);

    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
            '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox.light'
    }).addTo(map);

  L.control.zoom({
    position: 'topright'
    }
  ).addTo(map);

  var i = 0;

    L.geoJSON([bicycleRental], {
        pointToLayer: function (feature, latlng) {
            var myMarker = L.marker(latlng);
            i++;
            if (i <= 6) {
              var menuElement = document.getElementById('item'+i);
              menuElement.marker = myMarker;
            };
            return myMarker;
        }
    }).addTo(map);

</script>
</body>
</html>
  • Thanks Tomazic! I will implement what you suggested and the plugin and see if I get this thing going. – Noud Jun 5 at 8:38
  • Tougher than i thought it would be. I'm stuck again. I can see the marker as a property of the list item. Tried an eventlistener but don't know how to acces the marker and make it bounce when hovering over a list item. Installed the bounce plug-in just to see if that works, it does. Strugglin' JS beginner. – Noud Jun 6 at 15:28
  • I added simple tested example. – TomazicM Jun 6 at 20:11
  • 1
    @Noud If answer helped you, please mark it as accepted. And don't add your solution to the question. If you want to publish it, publish it as answer to your own question and remove it from the question. – TomazicM Jun 7 at 10:59
  • Gonna change that. – Noud Jun 7 at 15:39
1

Thanks TomazicM for the effort. Issue is solved as you already know. I added the el.marker.bounce(x) to the already existing highLightItem function. Thanks again helped a lot.

`const res = Array.from(document.querySelectorAll('.item'));
 console.log(res)

 function highLightItem () {

   for(const el of res){

    el.onmouseover = function (){
      mouseOver();
   }
 function mouseOver(){
    el.style.background = '#b2daff';
    el.marker.bounce(3 , {exclusive    : true,});
   }  
  }

  for(const el of res){
    el.onmouseout = function (){
     mouseOut();
  }
  function mouseOut(){
    el.style.background = '#99cdfe';
    }  
  }    
}

highLightItem();`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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