Adding Markers and Pop-ups

The last tutorial covered the basics of importing a basemap into a webpage with Leaflet. In this tutorial, we will ad some content to the basemap.

Let’s start with the page we wrote up last time:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
</script>
</body>
</html>

Save this into a new HTML file called marker.html. We can add a line to create a marker:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 

  var marker = L.marker([39.9, -75]).addTo(map); 
</script> 
</body> 
</html>

Much like the lines used to add the basemap, we add a marker using the ‘var’ element, to create a variable called ‘marker’ by invoking the script L.marker, giving it the option [46.5, -60.2] as the coordinates of the marker, then adding this to the element called ‘map’. Once that’s done, save everything in a file called marker.html and see how it looks in the browser. It should look something like this:


We can include a number of options to make our marker more interactive.  For instance, if we wanted to allow users to be able to move the marker by dragging it with their mouse we could add:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 

  var marker = L.marker([39.9, -75], {draggable: 'true' }).addTo(map); 
</script> 
</body> 
</html>

The resulting map should look something like this (try dragging the marker in this example):

If we wanted to add a second marker, we would need to create another variable with a different name, such as ‘marker2.’ We can also add the ‘opacity’ option to make this one somewhat transparent:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 

  var marker = L.marker([40, -75],
    {draggable: 'true'
    }).addTo(map);
  var marker2 = L.marker([39.91, -75.05],
    {opacity: '0.5'
    }).addTo(map);
</script> 
</body> 
</html>

The resulting map would look something like this:

If we had a number of points to mark on the map, we would add a variable for each marker and enter the coordinates accordingly.

We can create a type of marker that displays information, called a popup.

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
  
  var popup = L.popup()
    .setLatLng([39.910320, -75.028256])
    .setContent("This is a popup.")
    .openOn(map);
</script> 
</body> 
</html>

The resulting map has something like a speech bubble that displays the phrase entered under ‘.setContent.’ The same rules apply for adding additional popups, we just need to create a different variable, with a different name, and a different set of coordinates. It should look something like this:

We can create more elaborate popups

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
  
  var customPopup = "This is a Custom Popup";
  var customOptions =
    {
    'maxWidth': '500',
    'className' : 'custom'
    }
    L.marker([39.910320, -75.028256]).bindPopup(customPopup,customOptions).addTo(map);
</script> 
</body> 
</html>

Things are starting to get a little more elaborate. The variable ‘customPopup’ is about the same as what we’re used to, but the options are listed in a separate variable called customOptions. Further down there are some coordinates for a marker. Finally, the script ‘.bindPopup’ adds the two variables ‘customPopup’ and ‘customOptions’ to ‘map.’ The resulting map will have a marker that will display the popup when clicked upon. The resulting map should look something like this:

This format may seem more cumbersome than necessary, but it makes it easier to replicate popups without writing out the specific parameters every time. Suppose we wanted to add a second popup containing the same content and measurements. Because those parameters have already been defined, we would just need to add another version of the last line of the script:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
  
  var customPopup = "This is a Custom Popup";
  var customOptions =
    {
    'maxWidth': '500',
    'className' : 'custom'
    }
    L.marker([39.910320, -75.028256]).bindPopup(customPopup,customOptions).addTo(map);
    L.marker([39.92, -75.03]).bindPopup(customPopup,customOptions).addTo(map);
</script> 
</body> 
</html>

The resulting map now has two markers, each displaying the same popup. It should look like this:

Custom popups can display text and images. We can format the text by using tags similar to HTML tags and include an image by providing a url or file path to that image. Notice that we can also specify the width of the image:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
  
  var customPopup = "The Creek Bed, 2010<br/><img src='https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/NHL_Marl_Pit_2.JPG/1280px-NHL_Marl_Pit_2.JPG' width='350px'/>";
  var customOptions =
    {
    'maxWidth': '500',
    'className' : 'custom'
    }
    L.marker([39.910320, -75.028256]).bindPopup(customPopup,customOptions).addTo(map);
    
</script> 
</body> 
</html>

The map should look like this:


We can add a second marker, with different content by changing some of the variables:

<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<div id='map'></div>
<head>
</head>
<body>
<script>
  var map = L.map('map').setView([39.910320, -75.028256], 14);
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
    {attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
    }).addTo(map); 
  
  var customPopup = "The Creek Bed, 2010<br/><img src='https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/NHL_Marl_Pit_2.JPG/1280px-NHL_Marl_Pit_2.JPG' width='350px'/>";
  var customOptions =
    {
    'maxWidth': '500',
    'className' : 'custom'
    }
    L.marker([39.910320, -75.028256]).bindPopup(customPopup,customOptions).addTo(map);
    
    var customPopup2 = "Hadrosaurus Statue<br/>Lantern Lane<br/>Haddonfield, NJ<br/><img src='http://hadrosaurus.com/hadro_sculpture.jpg' width='350px'/>";
    L.marker([39.896909, -75.034466]).bindPopup(customPopup2,customOptions).addTo(map);
</script> 
</body> 
</html>

Notice, we created a variable called ‘customPopup2’ and called up that variable with ‘.bindPopup’, but relied on the same ‘customOptions’ defined when we created the first custom popup. It should look like this:

Adding markers and popups to your map provides an easy way to display information onto your basemap. Each item can be manipulated through a variety of options, which are listed in Leaflet’s Documentation page, to change their cosmetic appearance. As the example of the drag-able marker or the custom pop-up demonstrate, these can also used to create a responsive, interactive map.