inspector app has shared tile type detection

This commit is contained in:
Brandon Liu
2022-05-05 11:22:35 +08:00
parent ade6b7508e
commit e926399853
6 changed files with 129 additions and 47 deletions

View File

@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<link rel="icon" href="data:,">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<title>PMTiles Viewer</title>
</head>
<body>
<div id="root"></div>

View File

@@ -2,15 +2,13 @@ import { useState, useEffect } from "react";
import { styled, globalStyles } from "./stitches.config";
import Start from "./Start";
import Inspector from "./Inspector";
import LeafletMap from "./LeafletMap";
import MaplibreMap from "./MaplibreMap";
import Loader from "./Loader";
const Header = styled("div", {
height: "$4",
});
const GIT_SHA = import.meta.env.VITE_GIT_SHA.substr(0,8)
const GIT_SHA = (import.meta.env.VITE_GIT_SHA || "").substr(0,8)
function App() {
globalStyles();
@@ -30,7 +28,7 @@ function App() {
return (
<div>
<Header>pmtiles viewer | github | toggle | {GIT_SHA}</Header>
{file ? <MaplibreMap file={file} /> : <Start setFile={setFile} />}
{file ? <Loader file={file} /> : <Start setFile={setFile} />}
</div>
);
}

View File

@@ -2,7 +2,7 @@ import { useState } from "react";
import { PMTiles } from "../../js";
import { styled } from "./stitches.config";
function Inspector() {
function Inspector(props:{file:string}) {
return (
<>
foo

View File

@@ -8,7 +8,7 @@ const MapContainer = styled("div", {
height: "calc(100vh - $4)",
});
function LeafletMap(props:{file:string}) {
function LeafletMap(props:{file:string, tileType: string | null}) {
const p = new PMTiles(
"https://protomaps-static.sfo3.digitaloceanspaces.com/osm_carto.pmtiles"
);

55
app/src/Loader.tsx Normal file
View File

@@ -0,0 +1,55 @@
import { useState, useEffect } from "react";
import { PMTiles } from "../../js";
import { styled } from "./stitches.config";
import Inspector from "./Inspector";
import LeafletMap from "./LeafletMap";
import MaplibreMap from "./MaplibreMap";
function Loader(props: { file: string }) {
let [tab, setTab] = useState("maplibre");
let [tileType, setTileType] = useState<string | null>(null);
let view;
if (tab === "leaflet") {
view = <LeafletMap file={props.file} tileType={tileType}/>;
} else if (tab === "maplibre") {
view = <MaplibreMap file={props.file} tileType={tileType}/>;
} else {
view = <Inspector file={props.file} />;
}
useEffect(() => {
let pmtiles = new PMTiles(props.file);
const fetchData = async () => {
let metadata = await pmtiles.metadata();
let resp = await fetch(props.file, {
headers: { Range: "bytes=512000-512003" },
});
let magic = new DataView(await resp.arrayBuffer());
let b0 = magic.getUint8(0);
let b1 = magic.getUint8(1);
let b2 = magic.getUint8(2);
let b3 = magic.getUint8(3);
if (b0 == 0x89 && b1 == 0x50 && b2 == 0x4e && b3 == 0x47) {
setTileType("png");
} else if (b0 == 0xff && b1 == 0xd8 && b2 == 0xff && b3 == 0xe0) {
setTileType("jpg")
} else if (b0 == 0x1f && b1 == 0x8b) {
setTileType("mvt.gz");
} else {
setTileType("mvt");
}
};
fetchData();
}, [props.file]);
return <>
<div>{props.file} | {tileType}</div>
{view}
</>;
}
export default Loader;

View File

@@ -1,58 +1,87 @@
import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import { PMTiles, ProtocolCache } from "../../js";
import { styled } from "./stitches.config";
import maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css"
import "maplibre-gl/dist/maplibre-gl.css";
const MapContainer = styled("div", {
height: "calc(100vh - $4)",
});
function MaplibreMap(props:{file:string}) {
const rasterStyle = (file:string) => {
return {
version: 8,
sources: {
source: {
type: "raster",
tiles: ["pmtiles://" + file + "/{z}/{x}/{y}"],
maxzoom:4
},
},
layers: [
{
id: "raster",
type: "raster",
source: "source"
},
],
};
};
const vectorStyle = (file:string) => {
return {
version: 8,
sources: {
source: {
type: "vector",
tiles: ["pmtiles://" + file + "/{z}/{x}/{y}"],
maxzoom: 7,
},
},
layers: [
{
id: "zcta_fill",
type: "fill",
source: "source",
"source-layer": "zcta",
paint: {
"fill-color": "white",
},
},
{
id: "zcta_stroke",
type: "line",
source: "source",
"source-layer": "zcta",
paint: {
"line-color": "steelblue",
"line-width": 0.5,
},
},
],
};
};
function MaplibreMap(props: { file: string, tileType: string | null }) {
let mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
let cache = new ProtocolCache();
maplibregl.addProtocol("pmtiles", cache.protocol);
var style = {
"version": 8,
"sources": {
"zcta": {
"type": "vector",
"tiles": ["pmtiles://" + props.file + "/{z}/{x}/{y}"],
"maxzoom":7
}
},
"layers": [
{
"id": "zcta_fill",
"type": "fill",
"source":"zcta",
"source-layer":"zcta",
"paint": {
"fill-color":"white"
}
},
{
"id": "zcta_stroke",
"type": "line",
"source":"zcta",
"source-layer":"zcta",
"paint": {
"line-color":"steelblue",
"line-width":0.5
}
}
]
}
useEffect(() => {
const map = new maplibregl.Map({container:"map",zoom:3,center:[-101.43,44.34],style:style as any}); // TODO maplibre types
const map = new maplibregl.Map({
container: "map",
zoom: 0,
center: [0, 0],
style: rasterStyle(props.file) as any,
}); // TODO maplibre types (not any)
map.on("load", map.resize);
return () => {
map.remove();
};
}, []);
return <MapContainer id="map"></MapContainer>;
return <MapContainer id="map" ref={mapRef}></MapContainer>;
}
export default MaplibreMap;