45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
import type { OsmMap } from "esquisse"
|
|
|
|
/** The project's shared vector base style (Positron over the France pmtiles). */
|
|
const BASE_STYLE_URL =
|
|
"https://static.ppsfleet.navy/osm-data/styles/positron.json"
|
|
|
|
export interface MapView {
|
|
center: [number, number]
|
|
zoom: number
|
|
}
|
|
|
|
/**
|
|
* Build the interactive base map inside `container`.
|
|
*
|
|
* This is the only place that knows about the map library and the tile
|
|
* transport (esquisse + MapLibre + pmtiles) — the rendering layer never touches
|
|
* them. The libraries are imported lazily so they stay out of the server bundle:
|
|
* MapLibre needs a WebGL/DOM context that only exists in the browser.
|
|
*
|
|
* Returns the map instance, or `null` if it could not be created, so the caller
|
|
* shows an error state rather than letting an exception crash the UI.
|
|
*/
|
|
export async function createBaseMap(
|
|
container: HTMLElement,
|
|
view: MapView,
|
|
): Promise<OsmMap | null> {
|
|
try {
|
|
const [maplibreModule, pmtiles, { createMap }] = await Promise.all([
|
|
import("maplibre-gl"),
|
|
import("pmtiles"),
|
|
import("esquisse"),
|
|
])
|
|
return createMap({
|
|
maplibre: maplibreModule.default,
|
|
pmtiles,
|
|
container,
|
|
baseStyle: BASE_STYLE_URL,
|
|
center: view.center,
|
|
zoom: view.zoom,
|
|
})
|
|
} catch (error) {
|
|
console.error("createBaseMap: could not initialise the map", error)
|
|
return null
|
|
}
|
|
}
|