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 = 7710I 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: '© <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>
...