diff --git a/app/package-lock.json b/app/package-lock.json
index 0d9d6bb..5af3da1 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -28,6 +28,7 @@
"react-use": "^17.4.0"
},
"devDependencies": {
+ "@maplibre/maplibre-gl-style-spec": "^19.3.1",
"@types/d3-path": "^3.0.0",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/leaflet": "^1.7.9",
diff --git a/app/package.json b/app/package.json
index 1bddbc1..7d4b1df 100644
--- a/app/package.json
+++ b/app/package.json
@@ -30,6 +30,7 @@
"react-use": "^17.4.0"
},
"devDependencies": {
+ "@maplibre/maplibre-gl-style-spec": "^19.3.1",
"@types/d3-path": "^3.0.0",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/leaflet": "^1.7.9",
diff --git a/app/src/MaplibreMap.tsx b/app/src/MaplibreMap.tsx
index 76c811b..a4f7b55 100644
--- a/app/src/MaplibreMap.tsx
+++ b/app/src/MaplibreMap.tsx
@@ -8,10 +8,18 @@ import { MapGeoJSONFeature } from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
import { schemeSet3 } from "d3-scale-chromatic";
import base_theme from "protomaps-themes-base";
+import {
+ StyleSpecification,
+ LayerSpecification,
+} from "@maplibre/maplibre-gl-style-spec";
const INITIAL_ZOOM = 0;
const INITIAL_LNG = 0;
const INITIAL_LAT = 0;
+const BASEMAP_URL =
+ "https://api.protomaps.com/tiles/v3/{z}/{x}/{y}.mvt?key=1003762824b9687f";
+const BASEMAP_ATTRIBUTION =
+ 'Basemap Protomaps © OpenStreetMap';
maplibregl.setRTLTextPlugin(
"https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js",
@@ -169,14 +177,13 @@ const LayersVisibilityController = (props: {
);
};
-const rasterStyle = async (file: PMTiles): Promise => {
+const rasterStyle = async (file: PMTiles): Promise => {
let header = await file.getHeader();
let metadata = await file.getMetadata();
- let layers: any[] = [];
+ let layers: LayerSpecification[] = [];
if (metadata.type !== "baselayer") {
layers = base_theme("basemap", "black");
- layers[0].paint["background-color"] = "black";
}
layers.push({
@@ -196,10 +203,9 @@ const rasterStyle = async (file: PMTiles): Promise => {
},
basemap: {
type: "vector",
- tiles: [
- "https://api.protomaps.com/tiles/v3/{z}/{x}/{y}.mvt?key=1003762824b9687f",
- ],
- maxzoom: 14,
+ tiles: [BASEMAP_URL],
+ maxzoom: 15,
+ attribution: BASEMAP_ATTRIBUTION,
},
},
glyphs: "https://cdn.protomaps.com/fonts/pbf/{fontstack}/{range}.pbf",
@@ -207,18 +213,24 @@ const rasterStyle = async (file: PMTiles): Promise => {
};
};
-const vectorStyle = async (file: PMTiles): Promise => {
+const vectorStyle = async (
+ file: PMTiles
+): Promise<{
+ style: StyleSpecification;
+ layersVisibility: LayerVisibility[];
+}> => {
let header = await file.getHeader();
let metadata = await file.getMetadata();
- let layers: any[] = [];
+ let layers: LayerSpecification[] = [];
+ let baseOpacity = 0.35;
if (metadata.type !== "baselayer") {
layers = base_theme("basemap", "black");
- layers[0].paint["background-color"] = "black";
+ baseOpacity = 0.9;
}
var tilestats: any;
- var vector_layers: any;
+ var vector_layers: LayerSpecification[];
if (metadata.json) {
let j = JSON.parse(metadata.json);
tilestats = j.tilestats;
@@ -240,14 +252,14 @@ const vectorStyle = async (file: PMTiles): Promise => {
"fill-opacity": [
"case",
["boolean", ["feature-state", "hover"], false],
- 0.35,
- 0.2,
+ baseOpacity,
+ baseOpacity - 0.15,
],
"fill-outline-color": [
"case",
["boolean", ["feature-state", "hover"], false],
"hsl(0,100%,90%)",
- "rgba(0,0,0,0)",
+ "rgba(0,0,0,0.2)",
],
},
filter: ["==", ["geometry-type"], "Polygon"],
@@ -287,14 +299,12 @@ const vectorStyle = async (file: PMTiles): Promise => {
}
}
- for (let layer of layers) {
- if (layer["source-layer"] === "mask" && layer["type"] === "fill") {
- layer.paint["fill-color"] = "black";
- layer.paint["fill-opacity"] = 0.8;
- }
- }
-
- const bounds = [header.minLon, header.minLat, header.maxLon, header.maxLat];
+ const bounds: [number, number, number, number] = [
+ header.minLon,
+ header.minLat,
+ header.maxLon,
+ header.maxLat,
+ ];
return {
style: {
@@ -309,17 +319,16 @@ const vectorStyle = async (file: PMTiles): Promise => {
},
basemap: {
type: "vector",
- tiles: [
- "https://api.protomaps.com/tiles/v3/{z}/{x}/{y}.mvt?key=1003762824b9687f",
- ],
- maxzoom: 14,
+ tiles: [BASEMAP_URL],
+ maxzoom: 15,
bounds: bounds,
+ attribution: BASEMAP_ATTRIBUTION,
},
},
glyphs: "https://cdn.protomaps.com/fonts/pbf/{fontstack}/{range}.pbf",
layers: layers,
},
- layersVisibility: vector_layers.map((l: any) => ({
+ layersVisibility: vector_layers.map((l: LayerSpecification) => ({
id: l.id,
visible: true,
})),
@@ -455,7 +464,7 @@ function MaplibreMap(props: { file: PMTiles; mapHashPassed: boolean }) {
);
}
- let style: any; // TODO maplibre types (not any)
+ let style: StyleSpecification;
if (
header.tileType === TileType.Png ||
header.tileType === TileType.Webp ||