From 2fc62837b8501d2dd0503a06610f73c31b0aa86f Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Mon, 20 Jan 2025 17:07:01 +0800 Subject: [PATCH 1/2] refactor to support basemaps TileJSON in addition to PMTiles. --- app/src/MapView.tsx | 92 +++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/app/src/MapView.tsx b/app/src/MapView.tsx index c3eb5ab7..6e0621b1 100644 --- a/app/src/MapView.tsx +++ b/app/src/MapView.tsx @@ -19,6 +19,7 @@ import type { MapGeoJSONFeature, MapTouchEvent, StyleSpecification, + LngLatBoundsLike, } from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; import type { LayerSpecification } from "@maplibre/maplibre-gl-style-spec"; @@ -299,19 +300,17 @@ function MapLibreView(props: { map.on("idle", () => { setZoom(map.getZoom()); setError(undefined); - memoizedArchive() - ?.getMetadata() - .then((metadata) => { - if (metadata) { - const m = metadata as { - version?: string; - "planetiler:osm:osmosisreplicationtime"?: string; - }; - setTimelinessInfo( - `tiles@${m.version} ${m["planetiler:osm:osmosisreplicationtime"]?.substr(0, 10)}`, - ); - } - }); + archiveInfo().then((i) => { + if (i && i.metadata) { + const m = i.metadata as { + version?: string; + "planetiler:osm:osmosisreplicationtime"?: string; + }; + setTimelinessInfo( + `tiles@${m.version} ${m["planetiler:osm:osmosisreplicationtime"]?.substr(0, 10)}`, + ); + } + }); }); const showContextMenu = (e: MapTouchEvent) => { @@ -365,34 +364,39 @@ function MapLibreView(props: { }); // ensure the dropped archive is first added to the protocol - const memoizedArchive = () => { + const archiveInfo = async (): Promise< + { metadata: unknown; bounds: LngLatBoundsLike } | undefined + > => { const p = protocolRef(); if (p) { - if (props.droppedArchive) { - p.add(props.droppedArchive); - return props.droppedArchive; - } - if (props.tiles) { - let archive = p.tiles.get(props.tiles); + let archive = props.droppedArchive; + if (archive) { + p.add(archive); + } else if (props.tiles) { + archive = p.tiles.get(props.tiles); if (!archive) { archive = new PMTiles(props.tiles); p.add(archive); } - return archive; + } + if (archive) { + const metadata = await archive.getMetadata(); + const header = await archive.getHeader(); + return { + metadata: metadata, + bounds: [ + [header.minLon, header.minLat], + [header.maxLon, header.maxLat], + ], + }; } } }; const fit = async () => { - const header = await memoizedArchive()?.getHeader(); - if (header) { - mapRef?.fitBounds( - [ - [header.minLon, header.minLat], - [header.maxLon, header.maxLat], - ], - { animate: false }, - ); + const bounds = (await archiveInfo())?.bounds; + if (bounds) { + mapRef?.fitBounds(bounds, { animate: false }); } }; @@ -411,22 +415,20 @@ function MapLibreView(props: { const styleMajorVersion = props.npmVersion ? +props.npmVersion.split(".")[0] : STYLE_MAJOR_VERSION; - memoizedArchive() - ?.getMetadata() - .then((m) => { - if (m instanceof Object && "version" in m) { - const tilesetVersion = +(m.version as string).split(".")[0]; - if ( - VERSION_COMPATIBILITY[tilesetVersion].indexOf(styleMajorVersion) < 0 - ) { - setMismatch( - `style v${styleMajorVersion} may not be compatible with tileset v${tilesetVersion}. `, - ); - } else { - setMismatch(""); - } + archiveInfo().then((i) => { + if (i && i.metadata instanceof Object && "version" in i.metadata) { + const tilesetVersion = +(i.metadata.version as string).split(".")[0]; + if ( + VERSION_COMPATIBILITY[tilesetVersion].indexOf(styleMajorVersion) < 0 + ) { + setMismatch( + `style v${styleMajorVersion} may not be compatible with tileset v${tilesetVersion}. `, + ); + } else { + setMismatch(""); } - }); + } + }); }); createEffect(() => { From 462ff3bb5c1cbfd2ee7a220885f86567a8c13492 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Mon, 20 Jan 2025 17:20:41 +0800 Subject: [PATCH 2/2] Support TileJSON in addition to PMTiles for basemaps. --- app/src/MapView.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/src/MapView.tsx b/app/src/MapView.tsx index 6e0621b1..513dccf6 100644 --- a/app/src/MapView.tsx +++ b/app/src/MapView.tsx @@ -16,10 +16,10 @@ import { setRTLTextPlugin, } from "maplibre-gl"; import type { + LngLatBoundsLike, MapGeoJSONFeature, MapTouchEvent, StyleSpecification, - LngLatBoundsLike, } from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; import type { LayerSpecification } from "@maplibre/maplibre-gl-style-spec"; @@ -301,7 +301,7 @@ function MapLibreView(props: { setZoom(map.getZoom()); setError(undefined); archiveInfo().then((i) => { - if (i && i.metadata) { + if (i?.metadata) { const m = i.metadata as { version?: string; "planetiler:osm:osmosisreplicationtime"?: string; @@ -367,6 +367,18 @@ function MapLibreView(props: { const archiveInfo = async (): Promise< { metadata: unknown; bounds: LngLatBoundsLike } | undefined > => { + if (!props.droppedArchive && props.tiles?.endsWith(".json")) { + const resp = await fetch(props.tiles); + const tileJson = await resp.json(); + return { + metadata: tileJson, + bounds: [ + [tileJson.bounds[0], tileJson.bounds[1]], + [tileJson.bounds[2], tileJson.bounds[3]], + ], + }; + } + const p = protocolRef(); if (p) { let archive = props.droppedArchive;