Leaflet.js is an open-source JavaScript library for interactive maps. After copying a couple lines of code into your application, you have full access to the library. I’ve added two plugins, Leaflet.Arc for drawing great circle polylines and Leaflet.TextPath for displaying text labels above the polylines.

// site_analytics.html
{% block head %}
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
  integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ=="
  crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
  integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
  crossorigin=""></script>
<!-- Leaflet Plugins -->
{% sri_static 'leaflet_plugins/leaflet.textpath.js' %}
{% sri_static 'leaflet_plugins/leaflet-arc.min.js' %}
{% endblock head %}

I place leaflet.js code in a separate file and inject it into the template underneath a <div> tag.

// site_analytics.html
<div id="map"></div>
{% sri_static 'maps/leaflet_server_map.js' %}

In main.css, I set the map width to 100% of the container and the height to 40% of the viewport.

// main.css
#map{ 
  height: 40vh;
  width : 100%;
}

First, I add a map

// leaflet_map.js
var map = L.map('map', {
    center: [39, -98],
    zoom: 4,
});

Then, a scalebar

L.control.scale({ imperial: true, metric: true }).addTo(map); 

A basemap

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 20,
    attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);

Now we have a map centered at the geographic center of the US. Next, I add three markers for the cities of Los Angeles, Dallas, and NYC.

var LaLatLng = { lat: 34.1, lon: -118.2 }
var DallasLatLng = { lat: 32.8, lon: -96.8 }
var NYCLatLng = { lat: 40.7, lon: -73.9 }

For each marker, I include a title and alt text. I wanted to use a custom marker icon for the Dallas marker, so I found one on Flaticon. After adding the icon png to /static, I reference it from within the JavaScript file.

var IPAddressIcon = L.icon({
    iconUrl: "static/icons/ip-address.png",
    iconSize: [40, 40]
});
var DallasMarkerOptions = {
    title: "Blogthedata.com Server",
    alt: "The city of Dallas, Texas. USA",
    icon: IPAddressIcon
}

After adding the markers, I add polylines connecting the markers. The Polyline.Arc syntax is leveraging the Leaflet.Arc plugin to draw a great circle route. A plane would take this path when traveling between these locations.

var DallasToNYC = L.Polyline.Arc([DallasLatLng.lat, DallasLatLng.lon], [NYCLatLng.lat, NYCLatLng.lon], { color: 'orange' })

Next, I want to show the distance between the two cities. I could have hard-coded this, but it was easy enough to do it in the client since I am only performing a couple calculations.

var DallasToNYCDistance = (Math.floor(map.distance(DallasLatLng, NYCLatLng) / 1000)).toString()

With the distance as a string, I add it to the polyline and then add the polyline to the map.

DallasToNYC.setText(DallasToNYCDistance.concat(' km'), {
    center: true,
    offset: -5,
    attributes: { 'font-size': '24', 'font-weight': 'bold', fill: 'orange' }
})
DallasToNYC.addTo(map)

And we've got a map!

Comments

Back to Home
John Solly Profile Picture
John Solly Profile Picture

John Solly

A hands-on AI practitioner who transitioned to a CTO role to broaden my impact.

Most of my career has been dedicated to developing spatial systems at Esri, startups, and federal agencies. Currently, I lead technology strategy for Leidos' Health IT division, supporting agencies such as SSA, VA, and HHS.

My primary focus is the convergence of spatial computing and AI, enabling machines to interpret the physical world and applying these capabilities to meaningful missions.

Please reach out if you are interested in spatial systems or advancing AI within the federal government.