Skip to main content

alphaThis is a new frontend component. Help us improve it and give your feedback on Slack.

Getting started

Installation

npm install @defra/interactive-map@x.y.z-alpha

NOTE

Install using a fixed version (e.g. npm install @defra/interactive-map@x.y.z-alpha) as this package is currently in alpha and may introduce breaking changes. Check the GitHub releases page for the latest available version.

GOV.UK Prototype kit

The quickest way to get started is via the GOV.UK Prototype Kit. Once installed, the map component is available immediately — no build step or manual asset setup required.

The plugin automatically serves the required scripts and styles, and provides a ready-made map page template to build from.

See GOV.UK Prototype Kit - Install and use plugins for how to install plugins.

Manual setup

The package is shipped in two formats, ESM (ECMAScript Modules) and UMD (Universal Module Definition). If your project uses a bundler, such as webpack or Vite, use the ESM build and import the package directly in your JavaScript. If it doesn't, use the UMD build: copy the built files to your assets and load them with <script> tags.

The map component also requires a map provider — a separate library that handles the underlying tile rendering engine. The provider is passed in at initialisation, which keeps the core package lean and lets you choose the engine that fits your needs.

maplibre-gl is installed with this package (ESM) or bundled (UMD) — no separate install needed.

NOTE

With a bundler other than webpack or Vite (such as esbuild), set the MapLibre workerUrl option.

OpenLayers provider (optional)

An alternative to MapLibre with native support for British National Grid (EPSG:27700) coordinates. Install ol and proj4 separately:

npm install ol proj4
UMD:
ol and proj4 are bundled — no separate install needed.

ESRI provider (optional)

The ESRI provider is built for specific use cases, so it currently has a more limited set of features than MapLibre and OpenLayers. It's available for ESM projects only. Install @arcgis/core separately:

npm install @arcgis/core

Bundler configuration (ESM)

Some plugins work with more than one map provider. They load an adapter for your provider at runtime, and each adapter imports its own map engine. Only the adapter for your provider is ever loaded in the browser, but your bundler still builds every adapter, so it fails to resolve the engines you haven't installed:

Module not found: Error: Can't resolve 'ol/layer/Vector.js'

Tell your bundler to ignore the engines for the providers you don't use. Plugins that need this say so at the top of their documentation.

ProviderIgnorePattern
MapLibreol, proj4, @arcgis/core/^(ol|proj4|@arcgis\/core)(\/|$)/
OpenLayers@arcgis/core/^@arcgis\/core(\/|$)/
ESRIol, proj4/^(ol|proj4)(\/|$)/

The ignored engines are only used by adapters for other providers, which are never loaded, so nothing is missing at runtime. If you switch provider, update the pattern to match.

The examples below are for the MapLibre provider. For another provider, swap in its pattern.

Webpack

import webpack from 'webpack'
export default {
// ...
plugins: [
new webpack.IgnorePlugin({ resourceRegExp: /^(ol|proj4|@arcgis\/core)(\/|$)/ })
]
}

Vite

This applies to production builds; the dev server only warns.

export default {
build: {
rollupOptions: { // rolldownOptions in Vite 8+
external: [/^(ol|proj4|@arcgis\/core)(\/|$)/]
}
}
}

Rollup

export default {
// ...
external: [/^(ol|proj4|@arcgis\/core)(\/|$)/]
}

esbuild

await esbuild.build({
// ...
external: ['ol', 'ol/*', 'proj4', '@arcgis/core', '@arcgis/core/*']
})

Basic usage

ESM — add a container element to your HTML and initialise the map in your JavaScript:

<div id="map"></div>
import InteractiveMap from '@defra/interactive-map'
import maplibreProvider from '@defra/interactive-map/providers/maplibre'
import '@defra/interactive-map/css'
const interactiveMap = new InteractiveMap('map', {
mapProvider: maplibreProvider(),
behaviour: 'hybrid',
mapLabel: 'Ambleside',
zoom: 14,
center: [-2.968, 54.425],
containerHeight: '650px',
mapStyle: {
url: 'https://tiles.openfreemap.org/styles/liberty',
attribution: 'OpenFreeMap © OpenMapTiles Data from OpenStreetMap',
backgroundColor: '#f5f5f0'
}
})

UMD — copy the dist/umd/ folders to your assets, then use this page skeleton as a starting point:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Map</title>
<link rel="stylesheet" href="/your-assets-path/interactive-map.css">
<script defer src="/your-assets-path/interactive-map/index.js"></script>
<script defer src="/your-assets-path/maplibre-provider/index.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const interactiveMap = new defra.InteractiveMap('map', {
mapProvider: defra.maplibreProvider(),
behaviour: 'hybrid',
mapLabel: 'Ambleside',
zoom: 14,
center: [-2.968, 54.425],
containerHeight: '650px',
mapStyle: {
url: 'https://tiles.openfreemap.org/styles/liberty',
attribution: 'OpenFreeMap © OpenMapTiles Data from OpenStreetMap',
backgroundColor: '#f5f5f0'
}
})
})
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

NOTE

Load the scripts with defer and create the map inside a DOMContentLoaded listener, as above, so the page isn't blocked while they download. Don't use async, as the scripts must run in order.

Scripts are loaded dynamically — all files in each umd/ folder must be served from the same directory as their index.js.

Using plugins

ESM — add the plugin import alongside your existing core imports, then pass it to plugins:

import createInteractPlugin from '@defra/interactive-map/plugins/interact'
const interactiveMap = new InteractiveMap('map', {
// ...your existing options
plugins: [createInteractPlugin()]
})

UMD — copy the plugin's dist/umd/ folder to your assets if you haven't already, then add its script to your page skeleton:

<script defer src="/your-assets-path/interact-plugin/index.js"></script>

Then pass the plugin in your initialisation:

const interactiveMap = new defra.InteractiveMap('map', {
// ...your existing options
plugins: [defra.interactPlugin()]
})

The datasets, draw, frame, map-key, map-styles, menu, scale-bar and search plugins also have their own CSS. With ESM, import it alongside the plugin, for example import '@defra/interactive-map/plugins/datasets/css'. With UMD, copy the plugin's dist/css/index.css to your assets and add it to your page with a <link>.