Skip to content

Commit

Permalink
Move some stuff into stores here, mimicking the LTN app structure
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Jan 19, 2024
1 parent 803e674 commit 66a8034
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 39 deletions.
67 changes: 46 additions & 21 deletions web/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,22 @@
import NetworkLayer from "./NetworkLayer.svelte";
import RouteLayer from "./RouteLayer.svelte";
import ScoreLayer from "./ScoreLayer.svelte";
import {
mapContents,
map as mapStore,
mode,
model,
sidebarContents,
} from "./stores";
let model: MapModel | undefined = undefined;
let map: Map;
// TODO do the wasm stuff here
let mode: "score" | "route" = "score";
let map: Map;
$: if (map) {
mapStore.set(map);
}
// TODO all gonna move
let route_a: LngLat | null = null;
let route_b: LngLat | null = null;
let route_gj: FeatureCollection | null = null;
Expand All @@ -30,20 +40,20 @@
}
function zoomToFit() {
if (map && model) {
if (map && $model) {
// TODO wasteful
let bbox = turfBbox(JSON.parse(model.render()));
let bbox = turfBbox(JSON.parse($model.render()));
map.fitBounds(bbox, { animate: false });
}
}
function gotModel(_m: MapModel) {
if (!model) {
if (!$model) {
return;
}
console.log("New map model loaded");
zoomToFit();
let bbox = turfBbox(JSON.parse(model.render()));
let bbox = turfBbox(JSON.parse($model.render()));
route_a = {
lng: lerp(0.4, bbox[0], bbox[2]),
lat: lerp(0.4, bbox[1], bbox[3]),
Expand All @@ -53,12 +63,12 @@
lat: lerp(0.6, bbox[1], bbox[3]),
};
}
$: gotModel(model);
$: gotModel($model);
$: if (model && route_a && route_b) {
$: if ($model && route_a && route_b) {
try {
route_gj = JSON.parse(
model.compareRoute({
$model.compareRoute({
x1: route_a.lng,
y1: route_a.lat,
x2: route_b.lng,
Expand All @@ -71,20 +81,33 @@
route_err = err.toString();
}
}
let sidebarDiv: HTMLDivElement;
let mapDiv: HTMLDivElement;
$: if (sidebarDiv && $sidebarContents) {
sidebarDiv.innerHTML = "";
sidebarDiv.appendChild($sidebarContents);
}
$: if (mapDiv && $mapContents) {
mapDiv.innerHTML = "";
mapDiv.appendChild($mapContents);
}
</script>

<Layout>
<div slot="left">
<div bind:this={sidebarDiv} />

{#if map}
<MapLoader {map} bind:model />
<MapLoader />
{/if}
<div><button on:click={zoomToFit}>Zoom to fit</button></div>

<label>
<input bind:group={mode} type="radio" value="route" />Route
<input bind:group={$mode} type="radio" value="route" />Route
</label>
<label>
<input bind:group={mode} type="radio" value="score" />Score
<input bind:group={$mode} type="radio" value="score" />Score
</label>

<Legend
Expand All @@ -110,14 +133,14 @@
</label>
</div>

{#if mode == "route"}
{#if $mode == "route"}
{#if route_err}
<p>{route_err}</p>
{/if}
{#if route_gj}
<Directions {route_gj} />
{/if}
{:else if mode == "score"}
{:else if $mode == "score"}
<SequentialLegend {colorScale} {limits} />
{/if}
</div>
Expand All @@ -128,13 +151,15 @@
hash
bind:map
>
<div bind:this={mapDiv} />

<PolygonToolLayer />
{#if model}
{#if mode == "route"}
<NetworkLayer {model} {showSeverances} {opacity} />
<RouteLayer bind:route_a bind:route_b {route_gj} {map} />
{:else if mode == "score"}
<ScoreLayer {map} {model} {showSeverances} {opacity} />
{#if $model}
{#if $mode == "route"}
<NetworkLayer {showSeverances} {opacity} />
<RouteLayer bind:route_a bind:route_b {route_gj} />
{:else if $mode == "score"}
<ScoreLayer {showSeverances} {opacity} />
{/if}
{/if}
</MapLibre>
Expand Down
8 changes: 3 additions & 5 deletions web/src/MapLoader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import type { Map } from "maplibre-gl";
import { onMount } from "svelte";
import { Loading, OverpassSelector } from "./common";
export let model: MapModel | undefined = undefined;
export let map: Map;
import { map, model } from "./stores";
let example = "";
let msg: string | null = null;
Expand Down Expand Up @@ -39,7 +37,7 @@
function loadModel(buffer: ArrayBuffer) {
msg = "Building map model from OSM input";
console.time("load");
model = new MapModel(new Uint8Array(buffer));
$model = new MapModel(new Uint8Array(buffer));
console.timeEnd("load");
}
Expand Down Expand Up @@ -111,7 +109,7 @@
</div>

<OverpassSelector
{map}
map={$map}
on:gotXml={gotXml}
on:loading={(e) => (msg = e.detail)}
on:error={(e) => window.alert(e.detail)}
Expand Down
4 changes: 2 additions & 2 deletions web/src/NetworkLayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import { GeoJSON, hoverStateFilter, LineLayer, Popup } from "svelte-maplibre";
import { kindToColor } from "./colors";
import { constructMatchExpression, PropertiesTable } from "./common";
import { model } from "./stores";
export let model: MapModel;
// TODO Use filter expressions?
export let showSeverances: boolean;
export let opacity: number;
</script>

<GeoJSON data={JSON.parse(model.render())} generateId>
<GeoJSON data={JSON.parse($model.render())} generateId>
<LineLayer
id="network"
paint={{
Expand Down
6 changes: 3 additions & 3 deletions web/src/RouteLayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
import type { LngLat, Map, MapMouseEvent } from "maplibre-gl";
import { onDestroy, onMount } from "svelte";
import { GeoJSON, LineLayer, Marker } from "svelte-maplibre";
import { map } from "./stores";
export let route_a: LngLat;
export let route_b: LngLat;
export let route_gj: FeatureCollection;
export let map: Map;
onMount(() => {
map?.on("contextmenu", onRightClick);
$map?.on("contextmenu", onRightClick);
});
onDestroy(() => {
map?.off("contextmenu", onRightClick);
$map?.off("contextmenu", onRightClick);
});
function onRightClick(e: MapMouseEvent) {
// Move the first marker, for convenience
Expand Down
15 changes: 7 additions & 8 deletions web/src/ScoreLayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
} from "svelte-maplibre";
import { colorScale, kindToColor, limits } from "./colors";
import { constructMatchExpression, makeColorRamp } from "./common";
import { map, model } from "./stores";
export let model: MapModel;
export let map: Map;
export let showSeverances: boolean;
export let opacity: number;
Expand All @@ -25,7 +24,7 @@
try {
let linestring = e.detail.features[0].geometry.coordinates;
route_gj = JSON.parse(
model.compareRoute({
$model.compareRoute({
x1: linestring[0][0],
y1: linestring[0][1],
x2: linestring[1][0],
Expand All @@ -39,14 +38,14 @@
}
onMount(() => {
map?.on("click", onClick);
$map?.on("click", onClick);
});
onDestroy(() => {
map?.off("click", onClick);
$map?.off("click", onClick);
});
function onClick(e: MapMouseEvent) {
// If we click off a severance line, clear things
for (let f of map.queryRenderedFeatures(e.point, {
for (let f of $map.queryRenderedFeatures(e.point, {
layers: ["scores"],
})) {
return;
Expand All @@ -55,7 +54,7 @@
}
</script>

<GeoJSON data={JSON.parse(model.render())}>
<GeoJSON data={JSON.parse($model.render())}>
<LineLayer
id="network"
paint={{
Expand All @@ -77,7 +76,7 @@
}}
/>
</GeoJSON>
<GeoJSON data={JSON.parse(model.makeHeatmap())}>
<GeoJSON data={JSON.parse($model.makeHeatmap())}>
<LineLayer
id="scores"
paint={{
Expand Down
14 changes: 14 additions & 0 deletions web/src/SplitComponent.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
import { mapContents, sidebarContents } from "./stores";
// The kinda weird hack is that this must itself be nested underneath the
// MapLibre bit, so it has context. The sidebar is the "remote" part.
// TODO Maybe simplify accordingly
</script>

<div bind:this={$sidebarContents}>
<slot name="sidebar" />
</div>
<div bind:this={$mapContents}>
<slot name="map" />
</div>
12 changes: 12 additions & 0 deletions web/src/stores.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { MapModel } from "backend";
import type { Map } from "maplibre-gl";
import { writable, type Writable } from "svelte/store";

export let sidebarContents: Writable<HTMLDivElement | null> = writable(null);
export let mapContents: Writable<HTMLDivElement | null> = writable(null);

export type Mode = "score" | "route";

export let mode: Writable<Mode> = writable("score");
export let model: Writable<MapModel | null> = writable(null);
export let map: Writable<Map | null> = writable(null);

0 comments on commit 66a8034

Please sign in to comment.