import { useState, useEffect, useRef } from "react"; import { PMTiles, TileType } from "../../js"; import { Protocol } from "../../js/adapters" import { styled } from "./stitches.config"; import maplibregl from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; const MapContainer = styled("div", { height: "calc(100vh - $4 - $4)", }); const rasterStyle = (file: PMTiles) => { return { version: 8, sources: { source: { type: "raster", tiles: ["pmtiles://" + file.source.getKey() + "/{z}/{x}/{y}"], maxzoom: 4, }, }, layers: [ { id: "raster", type: "raster", source: "source", }, ], }; }; const vectorStyle = async (file: PMTiles): Promise => { let header = await file.getHeader(); let metadata = await file.getMetadata(); let layers: any[] = []; var tilestats:any; if (metadata.json) { let j = JSON.parse(metadata.json); tilestats = j.tilestats; } else { tilestats = metadata.tilestats; } if (tilestats) { for (let layer of tilestats.layers) { if (layer.geometry === "Polygon") { layers.push({ id: layer.layer + "_fill", type: "fill", source: "source", "source-layer": layer.layer, paint: { "fill-color": "white", }, }); } else if (layer.geometry === "LineString") { layers.push({ id: layer.layer + "_stroke", type: "line", source: "source", "source-layer": layer.layer, paint: { "line-color": "steelblue", "line-width": 0.5, }, }); } else { layers.push({ id: layer.layer + "_point", type: "circle", source: "source", "source-layer": layer.layer, paint: { "circle-color": "red", }, }); } } } else { layers.push({ id:"water", type:"fill", source:"source", "source-layer":"water", paint: { "fill-color":"blue" } }) layers.push({ id:"landuse", type:"fill", source:"source", "source-layer":"landuse", paint: { "fill-color":"green" } }) layers.push({ id:"roads", type:"line", source:"source", "source-layer":"roads", paint: { "line-color":"white", "line-width":0.5 } }) } return { version: 8, sources: { source: { type: "vector", tiles: ["pmtiles://" + file.source.getKey() + "/{z}/{x}/{y}"], minzoom: header.minZoom, maxzoom: header.maxZoom }, }, layers: layers, }; }; function MaplibreMap(props: { file: PMTiles }) { let mapContainerRef = useRef(null); let map: maplibregl.Map; useEffect(() => { let protocol = new Protocol(); maplibregl.addProtocol("pmtiles", protocol.tileFunc); protocol.add(props.file); // this is necessary for non-HTTP sources map = new maplibregl.Map({ container: mapContainerRef.current!, hash: true, zoom: 0, center: [0,0], style: { version: 8, sources: {}, layers: [], }, }); map.addControl(new maplibregl.NavigationControl({})); map.on("load", map.resize); return () => { map.remove(); }; }, []); useEffect(() => { let initStyle = async () => { if (map) { let header = await props.file.getHeader(); // map.fitBounds([ // [header.minLon, header.minLat], // [header.maxLon, header.maxLat], // ]); let style: any; // TODO maplibre types (not any) if (header.tileType === TileType.Png || header.tileType == TileType.Jpeg) { map.setStyle(rasterStyle(props.file) as any); } else { let style = await vectorStyle(props.file); map.setStyle(style); } } }; initStyle(); }, []); return ; } export default MaplibreMap;