diff --git a/app/src/MaplibreMap.tsx b/app/src/MaplibreMap.tsx index 090c103..68e6413 100644 --- a/app/src/MaplibreMap.tsx +++ b/app/src/MaplibreMap.tsx @@ -1,8 +1,10 @@ import { useState, useEffect, useRef } from "react"; +import { renderToString } from "react-dom/server"; import { PMTiles, TileType } from "../../js/index"; import { Protocol } from "../../js/adapters"; import { styled } from "./stitches.config"; import maplibregl from "maplibre-gl"; +import { MapGeoJSONFeature } from "maplibre-gl"; import "maplibre-gl/dist/maplibre-gl.css"; import { schemeSet3 } from "d3-scale-chromatic"; @@ -10,6 +12,38 @@ const MapContainer = styled("div", { height: "calc(100vh - $4 - $4)", }); +const PopupContainer = styled("div", { + color: "black", +}); + +const FeatureRow = styled("div", { + marginBottom: "0.5em", +}); + +const FeaturesProperties = (props: { features: MapGeoJSONFeature[] }) => { + const fs = props.features.map((f, i) => { + let tmp: [string, string][] = []; + for (var key in f.properties) { + tmp.push([key, f.properties[key]]); + } + + const rows = tmp.map((d, i) => ( + + {d[0]} + {d[1]} + + )); + + return ( + +
{(f.layer as any)["source-layer"]}
+ {rows}
+
+ ); + }); + return {fs}; +}; + const rasterStyle = (file: PMTiles) => { return { version: 8, @@ -47,7 +81,7 @@ const vectorStyle = async (file: PMTiles): Promise => { } if (vector_layers) { - for (let [i,layer] of vector_layers.entries()) { + for (let [i, layer] of vector_layers.entries()) { layers.push({ id: layer.id + "_fill", type: "fill", @@ -82,7 +116,7 @@ const vectorStyle = async (file: PMTiles): Promise => { }); } } else if (tilestats) { - for (let [i,layer] of tilestats.layers.entries()) { + for (let [i, layer] of tilestats.layers.entries()) { if (layer.geometry === "Polygon") { layers.push({ id: layer.layer + "_fill", @@ -157,6 +191,26 @@ function MaplibreMap(props: { file: PMTiles }) { map.addControl(new maplibregl.NavigationControl({})); map.on("load", map.resize); + const popup = new maplibregl.Popup({ + closeButton: false, + closeOnClick: false, + }); + + map.on("mousemove", (e) => { + var bbox = e.point; + var features = map.queryRenderedFeatures(bbox); + map.getCanvas().style.cursor = features.length ? "pointer" : ""; + + let content = renderToString(); + if (!features.length) { + popup.remove(); + } else { + popup.setHTML(content); + popup.setLngLat(e.lngLat); + popup.addTo(map); + } + }); + return () => { map.remove(); };