Leaflet is an open-source JavaScript library for displaying interactive maps on the web or mobile. A simple and lightweight library that will enable you to display and visualise location data and build dynamic applications.
What you'll need
OS Maps API and OS NGD API - Features added to an API project in the OS Data Hub with an API Key.
A text editor like Visual Studio Code or Notepad to edit and save your HTML and JavaScript files
Create a basic map
Step 1: Set Up Your HTML file
Create a new HTML file with a text editor (e.g. Notepad, Visual Studio Code)
Add the basic HTML structure to your file with a placeholder <div> for the map.
<!DOCTYPEhtml><htmllang="en"><head> <metacharset="UTF-8"> <metahttp-equiv="X-UA-Compatible"content="IE=edge"> <metaname="viewport"content="width=device-width, initial-scale=1.0"> <title>OS NGD API – Features | Template (EPSG:3857) | Leaflet</title><!--Add the Ordnance Survey Styling--> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/os-api-branding@0.3.1/os-api-branding.css" />
<scriptsrc="https://cdn.jsdelivr.net/gh/OrdnanceSurvey/os-api-branding@0.3.1/os-api-branding.js"></script><!--Add the Leaflet libraries--> <linkrel="stylesheet"href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <scriptsrc="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <style>/* Set the map container size and style */body { margin:0; padding:0; }#map { position:absolute; top:0; bottom:0; width:100%; } </style></head><body><!--Create a div element to hold the map--> <divid="map"></div><!--Add your Javascript code below--> <script>// Your Javascript code will go here </script></body></html>
Step 2: Insert your API Key and OS NGD Collection
To enable access to OS APIs an API key is required. Inside the <script> tag, add a variable called apiKey, replacing 'INSERT_API_KEY_HERE' with the API key from your project.
Add a variable called collectionID, replacing 'INSERT_COLLECTIONID_HERE' with the collection ID for the desired NGD Feature Type and version (e.g. bld-fts-buildingpart-1).
// Set API Key constapiKey='INSERT_API_KEY_HERE';constcollectionId='INSERT_COLLECTIONID_HERE';
Step 3: Add a basemap
Define the configuration options for the map, defining minZoom, maxZoom, center, zoom, maxBounds, attributionControl.
minZoom and maxZoom: Sets the minimum and maximum zoom level for the map. Users will not be able to go beyond these levels.
center: Sets the initial center point of the map.
zoom: Sets the initial zoom level of the map.
maxBounds: Defines the maximum bounds and restricts panning the map.
style: Defines the style of the map, configured via a URL pointing at the style specified.
attributionControl: When set to 'false', it hides the attribution control which displays map credits.
Initialize the map with the id of the <div> element and the configuration option defined in mapOptions.
Using the 'L.tileLayer' method, specify the basemap layer for OS Maps API, which includes your API Key to load the tiles to your map.
// Initialize the map.constmapOptions= { minZoom:7, maxZoom:20, center: [ 50.727589,-3.541809 ], zoom:18, maxBounds: [ [ 49.528423,-10.76418 ], [ 61.331151,1.9134116 ] ], attributionControl:false };constmap=L.map('map', mapOptions);// Load and display ZXY tile layer on the map.constbasemap=L.tileLayer(`https://api.os.uk/maps/raster/v1/zxy/Light_3857/{z}/{x}/{y}.png?key=${apiKey}`, { maxZoom:20 }).addTo(map);
Step 4: Add a OS NGD API - Features Layer.
Create a function called fetchFeatures that fetches the API based on the current map extent (bounding box) by generating a bbox string.
Construct the API request URL to fetch OS NGD data from the OS NGD API - Features. The URL includes the collectionId, bbox and apiKey.
Once the features have been returned in JSON, update the source data of the map's layers to display the features.
// Add layer group to make it easier to add or remove layers from the map.constlyrGroup=newL.layerGroup().addTo(map);// Define an asynchronous function to fetch and display the NGD Features API features.asyncfunctionfetchFeatures(bounds) {// Generate a BBOX string for the map extent.constbbox=bounds.toBBoxString();// Construct the NGD Features API request URL. const url = `https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?key=${apiKey}&bbox=${bbox}`;
// Fetch features from the API endpoint.constfeatures=awaitfetch(url).then(response =>response.json());// Parse the GeoJSON data and display it on the map.lyrGroup.clearLayers().addLayer(L.geoJSON(features)); }// Get the visible map bounds (BBOX).let bounds =map.getBounds();// Initial fetch and display of features.fetchFeatures(bounds);
Step 5: Load and update features on the map dynamically
Inside the map.on('moveend',...) event handler fetches and updates the features based on the map's current extent.
// Add event which will be triggered when the map has finshed moving (pan + zoom).// Implements a simple strategy to only request data when the map viewport invalidates// certain bounds.map.on('moveend',function() {let bounds1 =newL.latLngBounds(bounds.getSouthWest(),bounds.getNorthEast()), bounds2 =map.getBounds();if( JSON.stringify(bounds) !==JSON.stringify(bounds1.extend(bounds2)) ) { bounds = bounds2;fetchFeatures(bounds); } });
Features within the viewport extent will load initially (first 100 features) and continue to load as you pan and zoom across the map.
What's Next
Congratulations! You've successfully created a map using Leaflet and added an NGD layer using the OS NGD API - Features in a few steps. Continue to explore Ordnance Survey's code examples to learn more about advanced features and functionality such as adding markers, pop-ups, and additional layers.