maplibre-gl-esri-wayback
v0.2.2
Published
A MapLibre GL JS control for visualizing Esri World Imagery Wayback releases
Maintainers
Readme
MapLibre GL Esri Wayback
A MapLibre GL JS control for visualizing Esri World Imagery Wayback releases with a compact time slider.
Features
- MapLibre
IControlimplementation with a collapsible 29x29 control button. - Chronological Esri World Imagery Wayback time slider powered by
@esri/wayback-core. - Older and newer release buttons for precise one-release stepping.
- Basemap replacement behavior that keeps symbol layers visible as labels.
- Add the selected Wayback image as a persistent raster layer with an optional before-layer ID.
- "Only versions with local changes" filter that limits the timeline to the releases that actually changed at the current map center and zoom (mirrors Esri's option), refreshing as the map moves.
- Click-to-query imagery metadata for the selected release and location.
- TypeScript types, Vite library build, and React wrapper.
Installation
npm install maplibre-gl-esri-wayback maplibre-glQuick Start
Vanilla TypeScript
import maplibregl from 'maplibre-gl';
import { EsriWaybackControl } from 'maplibre-gl-esri-wayback';
import 'maplibre-gl-esri-wayback/style.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-100.05, 35.1],
zoom: 4,
});
map.on('load', () => {
const control = new EsriWaybackControl({
collapsed: false,
panelWidth: 320,
});
map.addControl(control, 'top-right');
});React
import { useEffect, useRef, useState } from 'react';
import maplibregl, { Map } from 'maplibre-gl';
import {
EsriWaybackControlReact,
useEsriWaybackState,
} from 'maplibre-gl-esri-wayback/react';
import 'maplibre-gl-esri-wayback/style.css';
function App() {
const mapContainer = useRef<HTMLDivElement>(null);
const [map, setMap] = useState<Map | null>(null);
const { state, setState } = useEsriWaybackState({ collapsed: false });
useEffect(() => {
if (!mapContainer.current) return;
const mapInstance = new maplibregl.Map({
container: mapContainer.current,
style: 'https://demotiles.maplibre.org/style.json',
center: [-100.05, 35.1],
zoom: 4,
});
mapInstance.on('load', () => setMap(mapInstance));
return () => mapInstance.remove();
}, []);
return (
<div style={{ width: '100%', height: '100vh' }}>
<div ref={mapContainer} style={{ width: '100%', height: '100%' }} />
{map && (
<EsriWaybackControlReact
map={map}
collapsed={state.collapsed}
onStateChange={setState}
/>
)}
</div>
);
}API
EsriWaybackControl
The main control class implementing MapLibre's IControl interface.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| collapsed | boolean | true | Whether the panel starts collapsed |
| position | string | 'top-right' | Control position on the map |
| title | string | 'Esri Wayback' | Panel title |
| panelWidth | number | 320 | Initial floating panel width in pixels |
| minPanelWidth | number | 260 | Minimum panel width when resizing |
| maxPanelWidth | number | 640 | Maximum panel width when resizing (also constrained to the map) |
| className | string | '' | Custom CSS class for the button container |
| initialReleaseNum | number | newest release | Release number to select after loading |
| sourceId | string | 'esri-wayback-source' | Raster source id |
| layerId | string | 'esri-wayback-layer' | Raster layer id |
| tileSize | number | 256 | Raster tile size |
| maxZoom | number | 23 | Raster source max zoom |
| metadataOnClick | boolean | true | Query metadata when the map is clicked |
| localChangesOnly | boolean | false | Start with the timeline filtered to versions with local changes |
Methods:
toggle(),expand(),collapse()selectRelease(releaseNum)setLocalChangesOnly(enabled)addSelectedReleaseAsPersistentLayer(beforeLayerId?)getState()setState(state)on(event, handler),off(event, handler)getMap(),getContainer()
Events:
collapseexpandstatechangereleasechangemetadatachangelocalchangeschangeerror
Only versions with local changes
Esri's Wayback viewer can hide releases that did not change a given location so
you don't have to step through dozens of identical images. This control exposes
the same behavior through a checkbox in the panel, the localChangesOnly option,
and the setLocalChangesOnly(enabled) method:
const control = new EsriWaybackControl({ localChangesOnly: true });
// or toggle it at runtime
control.setLocalChangesOnly(true);When enabled, the timeline is limited to the releases that introduced visible
imagery changes at the current map center and zoom (computed with
@esri/wayback-core's change detection), and it refreshes automatically as the
map moves. Listen for localchangeschange (or use the React
onLocalChangesChange prop) to react to the recomputed set.
EsriWaybackControlReact
React wrapper component for EsriWaybackControl.
Props include all control options plus:
| Prop | Type | Description |
|------|------|-------------|
| map | Map | MapLibre GL map instance |
| onStateChange | function | Callback fired when state changes |
| onReleaseChange | function | Callback fired when the selected release changes |
| onMetadataChange | function | Callback fired when metadata changes |
| onLocalChangesChange | function | Callback fired when the set of versions with local changes is recomputed |
| onError | function | Callback fired when an error is reported |
Development
npm install
npm run devAvailable scripts:
| Script | Description |
|--------|-------------|
| npm run dev | Start development server |
| npm run build | Build the library |
| npm run build:examples | Build examples for deployment |
| npm run test | Run tests |
| npm run test:coverage | Run tests with coverage |
Example routes:
http://localhost:5173/examples/basic/http://localhost:5173/examples/react/
Docker
docker build -t maplibre-gl-esri-wayback .
docker run -p 8080:80 maplibre-gl-esri-waybackOpen http://localhost:8080/maplibre-gl-esri-wayback/.
Attribution
This plugin uses @esri/wayback-core to retrieve Esri World Imagery Wayback releases and metadata. The imagery is subject to Esri's applicable terms of use.
