feat: make map reactive
All checks were successful
deploy to cloudflare pages / deploy (push) Successful in 35s

This commit is contained in:
uku 2024-10-23 11:24:05 +02:00
parent 080f8f80b3
commit b24cbc84bf
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
2 changed files with 47 additions and 30 deletions

View file

@ -11,8 +11,10 @@
</body> </body>
<style> <style>
html,
body { body {
margin: 0; margin: 0;
height: 100%;
} }
</style> </style>
</html> </html>

View file

@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from "./$types"; import type { PageData } from "./$types";
import { page } from "$app/stores";
import L from "leaflet"; import L from "leaflet";
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
@ -12,60 +11,76 @@
let { data }: Props = $props(); let { data }: Props = $props();
const lignes = data.lines; const lignes = data.lines;
const params = $page.url.searchParams; const point = L.latLng(45.75388713, 4.84715287);
const center = L.latLng(45.75388713, 4.84715287);
const bbox = lignes.bbox || [0, 0, 0, 0];
const center = L.latLng((bbox[1] + bbox[3]) / 2, (bbox[0] + bbox[2]) / 2);
const linesJson = lignes.features.map((feature) => {
let color = "rgb(" + feature.properties?.couleur?.replaceAll(" ", ",") + ")";
return L.geoJSON(feature, { style: { color } });
});
let latlng = $state(L.latLng(0, 0)); let latlng = $state(L.latLng(0, 0));
let distance = $derived(Math.max(0, latlng.distanceTo(center) - 20)); let distance = $derived(Math.max(0, latlng.distanceTo(point) - 20));
let points = $derived(5000 * Math.exp(-distance / 750)); let points = $derived(5000 * Math.exp(-distance / 750));
function createMap(node: HTMLElement) { let lines = $state(true);
const bbox = lignes.bbox || [0, 0, 0, 0]; let labels = $state(false);
const centerLat = (bbox[1] + bbox[3]) / 2;
const centerLon = (bbox[0] + bbox[2]) / 2;
const map = L.map(node).setView([centerLat, centerLon], 13); let map: L.Map | null = $state(null);
const mapSuffix = params.has("labels") ? "all" : "nolabels"; let tileLayer = $derived(
L.tileLayer(
L.tileLayer(`https://basemaps.cartocdn.com/light_${mapSuffix}/{z}/{x}/{y}{r}.png`, { `https://basemaps.cartocdn.com/light_${labels ? "all" : "nolabels"}/{z}/{x}/{y}{r}.png`,
{
attribution: attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>', '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
maxZoom: 20, maxZoom: 20,
}).addTo(map); },
),
);
if (params.has("lines")) { $effect(() => {
lignes.features.forEach((feature) => { if (!map) return;
let color = "black"; tileLayer.addTo(map);
if (feature.properties && feature.properties.couleur) { if (lines) {
color = "rgb(" + feature.properties.couleur.replaceAll(" ", ",") + ")"; linesJson.forEach((line) => map && line.addTo(map));
} else {
linesJson.forEach((line) => map && line.removeFrom(map));
} }
L.geoJSON(feature, { style: { color } }).addTo(map);
}); });
}
function createMap(node: HTMLElement) {
map = L.map(node).setView(center, 13);
const marker = L.marker([0, 0]); const marker = L.marker([0, 0]);
map.on("click", (e) => { map.on("click", (e) => {
marker.setLatLng(e.latlng).addTo(map); if (map) marker.setLatLng(e.latlng).addTo(map);
latlng = e.latlng; latlng = e.latlng;
}); });
} }
</script> </script>
<div id="info"> <div class="banner">
<span>distance: {distance}, points: {points}</span> <span>distance: {distance}, points: {points}</span>
</div> </div>
<div class="banner">
<label>lines: <input type="checkbox" bind:checked={lines} /></label>
<label>labels: <input type="checkbox" bind:checked={labels} /></label>
</div>
<div id="map" use:createMap></div> <div id="map" use:createMap></div>
<style> <style>
#info { .banner {
height: 5vh; padding: 4px;
text-align: center;
} }
#map { #map {
height: 95vh; height: 100%;
width: 100%; width: 100%;
} }
</style> </style>