☰

All pages on this website are written by myself, (C) Peter Thomson. I am a real person, not AI.

Leaflet Map tutorial - how to add markers and popups to an image or diagram displayed using leaflet

pageid = 5343 parentid = 7710

I have chosen the 360 panorama image as the basis for this tutorial as it is an example where I am probably going to use the technique on my website.

This frame shows a live view of the code we are creating:

The HTML code

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="leaflet.css" />
    <title>Add icons to a 360 degree rotation panoramic images using leaflet</title>
    <script type='text/javascript' src='leaflet.js'></script>
</head>
 
<body>
    <h1>Add icons to a 360 degree rotation panoramic images using leaflet</h1>
    <p>This isn't the best example of a 360 panorama! The stiching software has picked the foreground to match rather than the horizon, but it serves to illustrate the technique with leaflet..</p>
    <div id="image-map" style="width: 1000px; height: 1000px; border: 1px solid #AAA;"></div>
            <script>
    // Using leaflet.js to pan and zoom a big image.
    var map = L.map('image-map', {
      minZoom: 1,
      maxZoom: 4,
            center: [0, 0],
      zoom: 1,
      maxBoundsViscosity: 1,
      crs: L.CRS.Simple
      
    });
    // dimensions of the image
    // 21109 px * 1914 px at zoom 4 - full size
    // 10554  *  907 at zoom 3
    // 5277 * 453 at zoom 2
    // 2638 * 226 at zoom 1
    var diagramLayerGroup = new L.LayerGroup();
    var midimage= L.imageOverlay("pano360dartmoor2.jpg", [[0,0], [226,2683]]); // I think that should have been 2638, but I am not going to change it and reposition all the icons!
 
    diagramLayerGroup.addLayer(midimage);
     var markerGroup = diagramLayerGroup.addTo(map);
        // tell leaflet that the map is exactly as big as the image
     map.setMaxBounds(new L.LatLngBounds([0,0], [226,2683])); //size at zoom 1 - get the sizes right before you add markers!
     L.tileLayer('', {
    attribution: '&copy; <a href="https://peter-thomson.com">Peter Thomson 2018</a>'
}).addTo(map);
    var rightFlag = true;
    var leftFlag = true;
 
map.on('moveend', function(e){
    
    var z = map.getZoom();
    var mid = map.getCenter()
    lng = mid.lng
    lat = mid.lat
    console.log(mid+ 'zoom = ' + z +'  left '+leftFlag+' right ' + rightFlag);
    
    if (lng >370 && lng < 2380){
        rightFlag = true;
        leftFlag = true;
        return;
        }
     
     if(lng> 2390 && rightFlag){
         diagramLayerGroup.clearLayers();
        leftFlag = true;
         rightFlag= false;
         map.setView([lat,270], z);      
         diagramLayerGroup.addLayer(midimage);// I hoped that removing the image while the view is changed would add to the smoothness of the change, but I cannot see much difference
         
     }
      if(lng< 260 && leftFlag){ 
           rightFlag = true;
          leftFlag = false
         map.setView([lat,2300], z);
        
     }
     return;   
    });
    
/*
The code to display the 360 degree panorama is unchanged from the previous tutorial.
The new code below adds the marker icons to the image display.
The  function onMapClick(e) { makes it easy to get the coordinates for our markers. Click on the image displayed - zoom in to get it as precise as possible, and make a note of the coordinates for that point.
We then declare the icons we are going to use, and then create the code to add a marker for each of our points of interest.
Note that changing the size of the image or bounds changes the coordinates of a point on the image, so aim to have the image display finalised before you create the markers!

*/

       //add the code to display coordinates of a click on map - use this to place icons
    //note - don't change bounds after adding marker coordinates
    var popup = L.popup();
     function onMapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent("You clicked the map at " + e.latlng.toString())
            .openOn(map);
    }
    map.on('click', onMapClick);
    
     var DownIcon = L.Icon.extend({
     options: {
 
    iconSize:     [40, 40], // size of the icon
    iconAnchor:   [20, 40], // point of the icon which will correspond to marker's location
    popupAnchor:  [0, 0] // point from which the popup should open relative to the iconAnchor
    }
});
    
 var downblueIcon = new DownIcon({iconUrl: 'down-blue-icon.png'}),
    downyellowIcon = new DownIcon({iconUrl: 'down-yellow-icon.png'});
    mark1=L.marker([150.96666, 1314], {icon: downblueIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Leather Tor")).addTo(map);
    mark2=L.marker([164.933334, 1525], {icon: downblueIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Burrator")).addTo(map);
    mark3=L.marker([141.433334, 1774.5], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Burrator reservoir")).addTo(map);
    mark4=L.marker([196.616667, 679.3125], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("mast on North Hessary Tor")).addTo(map);
    mark5=L.marker([176.304167, 769.625], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Princetown")).addTo(map);
    mark6=L.marker([182.179167, 887.125], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("South Hessary Tor")).addTo(map);
    mark7=L.marker([150.108334, 901.625], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("River Meavy")).addTo(map);
    mark8=L.marker([161.716667, 1249.75], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Down Tor")).addTo(map);
    
    mark9=L.marker([138.933334, 2010], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Yelverton")).addTo(map);
    mark10=L.marker([142.933334, 2122], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Horrabridge")).addTo(map);
    mark11=L.marker([156.304167, 2303.75], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Tavistock")).addTo(map);
    mark12=L.marker([167.804167, 2488.75], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Brent Tor")).addTo(map);
    
    
    mark13=L.marker([171.233334, 406.875], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Little Staple Tor")).addTo(map);
    mark13=L.marker([173.483334, 421.125], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Staple Tor")).addTo(map);
    mark13=L.marker([166.054167, 431.8125], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Merrivale quarry")).addTo(map);
    
    mark13=L.marker([173.179167, 436.75], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Roos Tor")).addTo(map);
    mark13=L.marker([176.741667, 549.875], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Great Mis Tor")).addTo(map);
    mark13=L.marker([166.616667, 537.5625], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Kings Tor Quarry")).addTo(map);
    
    mark13=L.marker([149.433334, 1910], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Peek Hill")).addTo(map);
    mark13=L.marker([155.433334, 1854], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Plymouth")).addTo(map);
    mark13=L.marker([172.804167, 1035.8125], {icon: downyellowIcon}).bindPopup(L.popup({maxWidth:500}).setContent("Devonport leat")).addTo(map);
    
    </script>
</body>
</html>

...