mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 02:41:09 +00:00
* add line labels * allow loading remote and local tilesets without clearing the current tileset
This commit is contained in:
@@ -12,10 +12,12 @@ import {
|
|||||||
} from "maplibre-gl";
|
} from "maplibre-gl";
|
||||||
import { Compression, type Entry, tileIdToZxy, tileTypeExt } from "pmtiles";
|
import { Compression, type Entry, tileIdToZxy, tileTypeExt } from "pmtiles";
|
||||||
import {
|
import {
|
||||||
|
type Accessor,
|
||||||
For,
|
For,
|
||||||
type Setter,
|
type Setter,
|
||||||
Show,
|
Show,
|
||||||
createEffect,
|
createEffect,
|
||||||
|
createMemo,
|
||||||
createResource,
|
createResource,
|
||||||
createSignal,
|
createSignal,
|
||||||
onMount,
|
onMount,
|
||||||
@@ -343,16 +345,18 @@ function DirectoryTable(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ArchiveView(props: { genericTileset: Tileset }) {
|
function ArchiveView(props: { genericTileset: Accessor<Tileset> }) {
|
||||||
const tileset = () => {
|
const tileset = createMemo(() => {
|
||||||
if (props.genericTileset instanceof PMTilesTileset) {
|
console.log("memo!");
|
||||||
return props.genericTileset as PMTilesTileset;
|
const g = props.genericTileset();
|
||||||
|
if (g instanceof PMTilesTileset) {
|
||||||
|
return g as PMTilesTileset;
|
||||||
}
|
}
|
||||||
alert("This isn't a PMTiles archive!");
|
alert("This isn't a PMTiles archive!");
|
||||||
throw "This isn't a PMTiles tileset";
|
throw "This isn't a PMTiles tileset";
|
||||||
};
|
});
|
||||||
|
|
||||||
const [header] = createResource(tileset(), async (t) => {
|
const [header] = createResource(tileset, async (t) => {
|
||||||
return await t.archive.getHeader();
|
return await t.archive.getHeader();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -438,7 +442,7 @@ function ArchiveView(props: { genericTileset: Tileset }) {
|
|||||||
|
|
||||||
<DirectoryTable
|
<DirectoryTable
|
||||||
entries={rootEntries() || []}
|
entries={rootEntries() || []}
|
||||||
stateUrl={props.genericTileset.getStateUrl()}
|
stateUrl={props.genericTileset().getStateUrl()}
|
||||||
setHoveredTile={setHoveredTile}
|
setHoveredTile={setHoveredTile}
|
||||||
setOpenedLeaf={setOpenedLeaf}
|
setOpenedLeaf={setOpenedLeaf}
|
||||||
/>
|
/>
|
||||||
@@ -449,7 +453,7 @@ function ArchiveView(props: { genericTileset: Tileset }) {
|
|||||||
<div class="w-full flex flex-1 overflow-hidden">
|
<div class="w-full flex flex-1 overflow-hidden">
|
||||||
<DirectoryTable
|
<DirectoryTable
|
||||||
entries={l()}
|
entries={l()}
|
||||||
stateUrl={props.genericTileset.getStateUrl()}
|
stateUrl={props.genericTileset().getStateUrl()}
|
||||||
setHoveredTile={setHoveredTile}
|
setHoveredTile={setHoveredTile}
|
||||||
setOpenedLeaf={setOpenedLeaf}
|
setOpenedLeaf={setOpenedLeaf}
|
||||||
/>
|
/>
|
||||||
@@ -521,7 +525,7 @@ function PageArchive() {
|
|||||||
when={tileset()}
|
when={tileset()}
|
||||||
fallback={<ExampleChooser setTileset={setTileset} />}
|
fallback={<ExampleChooser setTileset={setTileset} />}
|
||||||
>
|
>
|
||||||
{(t) => <ArchiveView genericTileset={t()} />}
|
{(t) => <ArchiveView genericTileset={t} />}
|
||||||
</Show>
|
</Show>
|
||||||
</Frame>
|
</Frame>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ declare module "solid-js" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function MapView(props: {
|
function MapView(props: {
|
||||||
tileset: Tileset;
|
tileset: Accessor<Tileset>;
|
||||||
showMetadata: Accessor<boolean>;
|
showMetadata: Accessor<boolean>;
|
||||||
setShowMetadata: Setter<boolean>;
|
setShowMetadata: Setter<boolean>;
|
||||||
showTileBoundaries: Accessor<boolean>;
|
showTileBoundaries: Accessor<boolean>;
|
||||||
@@ -83,6 +83,164 @@ function MapView(props: {
|
|||||||
addProtocol("pmtiles", protocol.tile);
|
addProtocol("pmtiles", protocol.tile);
|
||||||
|
|
||||||
let map: MaplibreMap;
|
let map: MaplibreMap;
|
||||||
|
let initialLoad = true;
|
||||||
|
|
||||||
|
const roundZoom = () => {
|
||||||
|
map.zoomTo(Math.round(map.getZoom()));
|
||||||
|
};
|
||||||
|
|
||||||
|
const fitToBounds = async () => {
|
||||||
|
const bounds = await props.tileset().getBounds();
|
||||||
|
map.fitBounds(
|
||||||
|
[
|
||||||
|
[bounds[0], bounds[1]],
|
||||||
|
[bounds[2], bounds[3]],
|
||||||
|
],
|
||||||
|
{ animate: false },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTileset = () => {
|
||||||
|
for (const layer of map.getStyle().layers) {
|
||||||
|
if ("source" in layer && layer.source === "tileset") {
|
||||||
|
map.removeLayer(layer.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map.removeSource("tileset");
|
||||||
|
};
|
||||||
|
|
||||||
|
const addTileset = async (tileset: Tileset) => {
|
||||||
|
const archiveForProtocol = tileset.archiveForProtocol();
|
||||||
|
if (archiveForProtocol) {
|
||||||
|
protocol.add(archiveForProtocol);
|
||||||
|
}
|
||||||
|
let flavor = "white";
|
||||||
|
if (window.matchMedia?.("(prefers-color-scheme: dark)").matches) {
|
||||||
|
flavor = "black";
|
||||||
|
}
|
||||||
|
if (await tileset.isOverlay()) {
|
||||||
|
setBasemap(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await tileset.isVector()) {
|
||||||
|
map.addSource("tileset", {
|
||||||
|
type: "vector",
|
||||||
|
url: tileset.getMaplibreSourceUrl(),
|
||||||
|
});
|
||||||
|
const vectorLayers = await tileset.getVectorLayers();
|
||||||
|
setLayerVisibility(vectorLayers.map((v) => ({ id: v, visible: true })));
|
||||||
|
for (const [i, vectorLayer] of vectorLayers.entries()) {
|
||||||
|
map.addLayer({
|
||||||
|
id: `tileset_fill_${vectorLayer}`,
|
||||||
|
type: "fill",
|
||||||
|
source: "tileset",
|
||||||
|
"source-layer": vectorLayer,
|
||||||
|
paint: {
|
||||||
|
"fill-color": colorForIdx(i),
|
||||||
|
"fill-opacity": [
|
||||||
|
"case",
|
||||||
|
["boolean", ["feature-state", "hover"], false],
|
||||||
|
0.25,
|
||||||
|
0.1,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
filter: ["==", ["geometry-type"], "Polygon"],
|
||||||
|
});
|
||||||
|
map.addLayer({
|
||||||
|
id: `tileset_line_${vectorLayer}`,
|
||||||
|
type: "line",
|
||||||
|
source: "tileset",
|
||||||
|
"source-layer": vectorLayer,
|
||||||
|
paint: {
|
||||||
|
"line-color": colorForIdx(i),
|
||||||
|
"line-width": [
|
||||||
|
"case",
|
||||||
|
["boolean", ["feature-state", "hover"], false],
|
||||||
|
2,
|
||||||
|
0.5,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
filter: ["==", ["geometry-type"], "LineString"],
|
||||||
|
});
|
||||||
|
map.addLayer({
|
||||||
|
id: `tileset_circle_${vectorLayer}`,
|
||||||
|
type: "circle",
|
||||||
|
source: "tileset",
|
||||||
|
"source-layer": vectorLayer,
|
||||||
|
paint: {
|
||||||
|
"circle-color": colorForIdx(i),
|
||||||
|
"circle-radius": 3,
|
||||||
|
"circle-stroke-color": "white",
|
||||||
|
"circle-stroke-width": [
|
||||||
|
"case",
|
||||||
|
["boolean", ["feature-state", "hover"], false],
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
filter: ["==", ["geometry-type"], "Point"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (const [i, vectorLayer] of vectorLayers.entries()) {
|
||||||
|
map.addLayer({
|
||||||
|
id: `tileset_line_label_${vectorLayer}`,
|
||||||
|
type: "symbol",
|
||||||
|
source: "tileset",
|
||||||
|
"source-layer": vectorLayer,
|
||||||
|
layout: {
|
||||||
|
"text-field": ["get", "name"],
|
||||||
|
"text-font": ["Noto Sans Regular"],
|
||||||
|
"text-size": 10,
|
||||||
|
"symbol-placement": "line",
|
||||||
|
},
|
||||||
|
paint: {
|
||||||
|
"text-color": colorForIdx(i),
|
||||||
|
"text-halo-color": flavor,
|
||||||
|
"text-halo-width": 2,
|
||||||
|
},
|
||||||
|
filter: ["==", ["geometry-type"], "LineString"],
|
||||||
|
});
|
||||||
|
map.addLayer({
|
||||||
|
id: `tileset_point_label_${vectorLayer}`,
|
||||||
|
type: "symbol",
|
||||||
|
source: "tileset",
|
||||||
|
"source-layer": vectorLayer,
|
||||||
|
layout: {
|
||||||
|
"text-field": ["get", "name"],
|
||||||
|
"text-font": ["Noto Sans Regular"],
|
||||||
|
"text-size": 10,
|
||||||
|
"text-offset": [0, -1],
|
||||||
|
},
|
||||||
|
paint: {
|
||||||
|
"text-color": colorForIdx(i),
|
||||||
|
"text-halo-color": flavor,
|
||||||
|
"text-halo-width": 2,
|
||||||
|
},
|
||||||
|
filter: ["==", ["geometry-type"], "Point"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
map.addSource("tileset", {
|
||||||
|
type: "raster",
|
||||||
|
url: tileset.getMaplibreSourceUrl(),
|
||||||
|
});
|
||||||
|
map.addLayer({
|
||||||
|
source: "tileset",
|
||||||
|
id: "tileset_raster",
|
||||||
|
type: "raster",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const tileset = props.tileset();
|
||||||
|
if (initialLoad) {
|
||||||
|
initialLoad = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeTileset();
|
||||||
|
addTileset(tileset);
|
||||||
|
});
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const visibility = basemap() ? "visible" : "none";
|
const visibility = basemap() ? "visible" : "none";
|
||||||
@@ -95,9 +253,39 @@ function MapView(props: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const roundZoom = () => {
|
createEffect(() => {
|
||||||
map.zoomTo(Math.round(map.getZoom()));
|
const show = props.showTileBoundaries();
|
||||||
};
|
if (map) {
|
||||||
|
map.showTileBoundaries = show;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (props.inspectFeatures()) {
|
||||||
|
setFrozen(false);
|
||||||
|
} else {
|
||||||
|
for (const hoveredFeature of hoveredFeatures()) {
|
||||||
|
map.setFeatureState(hoveredFeature, { hover: false });
|
||||||
|
}
|
||||||
|
popup.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
const setVisibility = (layerName: string, visibility: string) => {
|
||||||
|
if (map.getLayer(layerName)) {
|
||||||
|
map.setLayoutProperty(layerName, "visibility", visibility);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const { id, visible } of layerVisibility()) {
|
||||||
|
const visibility = visible ? "visible" : "none";
|
||||||
|
setVisibility(`tileset_fill_${id}`, visibility);
|
||||||
|
setVisibility(`tileset_line_${id}`, visibility);
|
||||||
|
setVisibility(`tileset_circle_${id}`, visibility);
|
||||||
|
setVisibility(`tileset_point_label_${id}`, visibility);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (!mapContainer) {
|
if (!mapContainer) {
|
||||||
@@ -105,11 +293,6 @@ function MapView(props: {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const archiveForProtocol = props.tileset.archiveForProtocol();
|
|
||||||
if (archiveForProtocol) {
|
|
||||||
protocol.add(archiveForProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getRTLTextPluginStatus() === "unavailable") {
|
if (getRTLTextPluginStatus() === "unavailable") {
|
||||||
setRTLTextPlugin(
|
setRTLTextPlugin(
|
||||||
"https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js",
|
"https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js",
|
||||||
@@ -154,21 +337,6 @@ function MapView(props: {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
map.showTileBoundaries = props.showTileBoundaries();
|
|
||||||
});
|
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
if (props.inspectFeatures()) {
|
|
||||||
setFrozen(false);
|
|
||||||
} else {
|
|
||||||
for (const hoveredFeature of hoveredFeatures()) {
|
|
||||||
map.setFeatureState(hoveredFeature, { hover: false });
|
|
||||||
}
|
|
||||||
popup.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
map.addControl(new NavigationControl({}), "top-left");
|
map.addControl(new NavigationControl({}), "top-left");
|
||||||
map.addControl(new AttributionControl({ compact: false }), "bottom-right");
|
map.addControl(new AttributionControl({ compact: false }), "bottom-right");
|
||||||
|
|
||||||
@@ -206,7 +374,7 @@ function MapView(props: {
|
|||||||
|
|
||||||
const currentZoom = zoom();
|
const currentZoom = zoom();
|
||||||
const sp = new SphericalMercator();
|
const sp = new SphericalMercator();
|
||||||
const maxZoom = await props.tileset.getMaxZoom();
|
const maxZoom = await props.tileset().getMaxZoom();
|
||||||
const z = Math.max(0, Math.min(maxZoom, Math.floor(currentZoom)));
|
const z = Math.max(0, Math.min(maxZoom, Math.floor(currentZoom)));
|
||||||
const result = sp.px([e.lngLat.lng, e.lngLat.lat], z);
|
const result = sp.px([e.lngLat.lng, e.lngLat.lat], z);
|
||||||
const tileX = Math.floor(result[0] / 256);
|
const tileX = Math.floor(result[0] / 256);
|
||||||
@@ -222,7 +390,7 @@ function MapView(props: {
|
|||||||
class="block text-xs btn-primary mt-2 text-center"
|
class="block text-xs btn-primary mt-2 text-center"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
href={tileInspectUrl(props.tileset.getStateUrl(), [
|
href={tileInspectUrl(props.tileset().getStateUrl(), [
|
||||||
z,
|
z,
|
||||||
tileX,
|
tileX,
|
||||||
tileY,
|
tileY,
|
||||||
@@ -245,131 +413,11 @@ function MapView(props: {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map.on("load", async () => {
|
map.on("load", async () => {
|
||||||
if (await props.tileset.isOverlay()) {
|
await addTileset(props.tileset());
|
||||||
setBasemap(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await props.tileset.isVector()) {
|
|
||||||
map.addSource("tileset", {
|
|
||||||
type: "vector",
|
|
||||||
url: props.tileset.getMaplibreSourceUrl(),
|
|
||||||
});
|
|
||||||
const vectorLayers = await props.tileset.getVectorLayers();
|
|
||||||
setLayerVisibility(vectorLayers.map((v) => ({ id: v, visible: true })));
|
|
||||||
for (const [i, vectorLayer] of vectorLayers.entries()) {
|
|
||||||
map.addLayer({
|
|
||||||
id: `tileset_fill_${vectorLayer}`,
|
|
||||||
type: "fill",
|
|
||||||
source: "tileset",
|
|
||||||
"source-layer": vectorLayer,
|
|
||||||
paint: {
|
|
||||||
"fill-color": colorForIdx(i),
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "hover"], false],
|
|
||||||
0.25,
|
|
||||||
0.1,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
filter: ["==", ["geometry-type"], "Polygon"],
|
|
||||||
});
|
|
||||||
map.addLayer({
|
|
||||||
id: `tileset_line_${vectorLayer}`,
|
|
||||||
type: "line",
|
|
||||||
source: "tileset",
|
|
||||||
"source-layer": vectorLayer,
|
|
||||||
paint: {
|
|
||||||
"line-color": colorForIdx(i),
|
|
||||||
"line-width": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "hover"], false],
|
|
||||||
2,
|
|
||||||
0.5,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
filter: ["==", ["geometry-type"], "LineString"],
|
|
||||||
});
|
|
||||||
map.addLayer({
|
|
||||||
id: `tileset_circle_${vectorLayer}`,
|
|
||||||
type: "circle",
|
|
||||||
source: "tileset",
|
|
||||||
"source-layer": vectorLayer,
|
|
||||||
paint: {
|
|
||||||
"circle-color": colorForIdx(i),
|
|
||||||
"circle-radius": 3,
|
|
||||||
"circle-stroke-color": "white",
|
|
||||||
"circle-stroke-width": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "hover"], false],
|
|
||||||
3,
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
filter: ["==", ["geometry-type"], "Point"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (const [i, vectorLayer] of vectorLayers.entries()) {
|
|
||||||
map.addLayer({
|
|
||||||
id: `tileset_point_label_${vectorLayer}`,
|
|
||||||
type: "symbol",
|
|
||||||
source: "tileset",
|
|
||||||
"source-layer": vectorLayer,
|
|
||||||
layout: {
|
|
||||||
"text-field": ["get", "name"],
|
|
||||||
"text-font": ["Noto Sans Regular"],
|
|
||||||
"text-size": 10,
|
|
||||||
"text-offset": [0, -1],
|
|
||||||
},
|
|
||||||
paint: {
|
|
||||||
"text-color": colorForIdx(i),
|
|
||||||
"text-halo-color": flavor,
|
|
||||||
"text-halo-width": 2,
|
|
||||||
},
|
|
||||||
filter: ["==", ["geometry-type"], "Point"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
map.addSource("tileset", {
|
|
||||||
type: "raster",
|
|
||||||
url: props.tileset.getMaplibreSourceUrl(),
|
|
||||||
});
|
|
||||||
map.addLayer({
|
|
||||||
source: "tileset",
|
|
||||||
id: "tileset_raster",
|
|
||||||
type: "raster",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
map.resize();
|
map.resize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const fitToBounds = async () => {
|
|
||||||
const bounds = await props.tileset.getBounds();
|
|
||||||
map.fitBounds(
|
|
||||||
[
|
|
||||||
[bounds[0], bounds[1]],
|
|
||||||
[bounds[2], bounds[3]],
|
|
||||||
],
|
|
||||||
{ animate: false },
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
const setVisibility = (layerName: string, visibility: string) => {
|
|
||||||
if (map.getLayer(layerName)) {
|
|
||||||
map.setLayoutProperty(layerName, "visibility", visibility);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const { id, visible } of layerVisibility()) {
|
|
||||||
const visibility = visible ? "visible" : "none";
|
|
||||||
setVisibility(`tileset_fill_${id}`, visibility);
|
|
||||||
setVisibility(`tileset_line_${id}`, visibility);
|
|
||||||
setVisibility(`tileset_circle_${id}`, visibility);
|
|
||||||
setVisibility(`tileset_point_label_${id}`, visibility);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex flex-col md:flex-row w-full h-full">
|
<div class="flex flex-col md:flex-row w-full h-full">
|
||||||
<div class="flex-1 flex flex-col">
|
<div class="flex-1 flex flex-col">
|
||||||
@@ -458,9 +506,9 @@ function MapView(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonView = (props: { tileset: Tileset }) => {
|
const JsonView = (props: { tileset: Accessor<Tileset> }) => {
|
||||||
const [data] = createResource(async () => {
|
const [data] = createResource(async () => {
|
||||||
return await props.tileset.getMetadata();
|
return await props.tileset().getMetadata();
|
||||||
});
|
});
|
||||||
|
|
||||||
return <json-viewer data={data()} />;
|
return <json-viewer data={data()} />;
|
||||||
@@ -517,7 +565,7 @@ function PageMap() {
|
|||||||
>
|
>
|
||||||
{(t) => (
|
{(t) => (
|
||||||
<MapView
|
<MapView
|
||||||
tileset={t()}
|
tileset={t}
|
||||||
showMetadata={showMetadata}
|
showMetadata={showMetadata}
|
||||||
setShowMetadata={setShowMetadata}
|
setShowMetadata={setShowMetadata}
|
||||||
showTileBoundaries={showTileBoundaries}
|
showTileBoundaries={showTileBoundaries}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
type Setter,
|
type Setter,
|
||||||
Show,
|
Show,
|
||||||
createEffect,
|
createEffect,
|
||||||
|
createMemo,
|
||||||
createResource,
|
createResource,
|
||||||
createSignal,
|
createSignal,
|
||||||
onMount,
|
onMount,
|
||||||
@@ -104,7 +105,7 @@ function layerFeatureCounts(
|
|||||||
|
|
||||||
function ZoomableTile(props: {
|
function ZoomableTile(props: {
|
||||||
zxy: Accessor<[number, number, number]>;
|
zxy: Accessor<[number, number, number]>;
|
||||||
tileset: Tileset;
|
tileset: Accessor<Tileset>;
|
||||||
}) {
|
}) {
|
||||||
let containerRef: HTMLDivElement | undefined;
|
let containerRef: HTMLDivElement | undefined;
|
||||||
let svg: Selection<SVGSVGElement, unknown, null, undefined>;
|
let svg: Selection<SVGSVGElement, unknown, null, undefined>;
|
||||||
@@ -211,20 +212,27 @@ function ZoomableTile(props: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const [parsedTile] = createResource(props.zxy, async (zxy) => {
|
const inputs = createMemo(() => ({
|
||||||
const tileset = props.tileset;
|
zxy: props.zxy(),
|
||||||
|
tileset: props.tileset(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const [parsedTile] = createResource(inputs, async (i) => {
|
||||||
|
const tileset = i.tileset;
|
||||||
|
const zxy = i.zxy;
|
||||||
if (await tileset.isVector()) {
|
if (await tileset.isVector()) {
|
||||||
const data = await tileset.getZxy(zxy[0], zxy[1], zxy[2]);
|
const data = await tileset.getZxy(zxy[0], zxy[1], zxy[2]);
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
const vectorLayers = await props.tileset.getVectorLayers();
|
const vectorLayers = await props.tileset().getVectorLayers();
|
||||||
return parseTile(data, vectorLayers);
|
return parseTile(data, vectorLayers);
|
||||||
}
|
}
|
||||||
return await tileset.getZxy(zxy[0], zxy[1], zxy[2]);
|
return await tileset.getZxy(zxy[0], zxy[1], zxy[2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
onMount(async () => {
|
createEffect(async () => {
|
||||||
if (await props.tileset.isVector()) {
|
const tileset = props.tileset();
|
||||||
const vectorLayers = await props.tileset.getVectorLayers();
|
if (await tileset.isVector()) {
|
||||||
|
const vectorLayers = await tileset.getVectorLayers();
|
||||||
setLayerVisibility(vectorLayers.map((v) => ({ id: v, visible: true })));
|
setLayerVisibility(vectorLayers.map((v) => ({ id: v, visible: true })));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -315,7 +323,7 @@ function ZoomableTile(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TileView(props: {
|
function TileView(props: {
|
||||||
tileset: Tileset;
|
tileset: Accessor<Tileset>;
|
||||||
zxy: Accessor<[number, number, number] | undefined>;
|
zxy: Accessor<[number, number, number] | undefined>;
|
||||||
setZxy: Setter<[number, number, number] | undefined>;
|
setZxy: Setter<[number, number, number] | undefined>;
|
||||||
}) {
|
}) {
|
||||||
@@ -523,7 +531,7 @@ function PageTile() {
|
|||||||
when={tileset()}
|
when={tileset()}
|
||||||
fallback={<ExampleChooser setTileset={setTileset} />}
|
fallback={<ExampleChooser setTileset={setTileset} />}
|
||||||
>
|
>
|
||||||
{(t) => <TileView tileset={t()} zxy={zxy} setZxy={setZxy} />}
|
{(t) => <TileView tileset={t} zxy={zxy} setZxy={setZxy} />}
|
||||||
</Show>
|
</Show>
|
||||||
</Frame>
|
</Frame>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user