|
24 | 24 | filterGeo,
|
25 | 25 | jenksBreaks,
|
26 | 26 | quantileBreaks,
|
| 27 | + createPaintObjectFromMetric, |
| 28 | + extractVectorMetricValues, |
27 | 29 | } from "./mapUtils.js";
|
28 | 30 | import NonStandardControls from "./NonStandardControls.svelte";
|
29 | 31 | import { replaceState } from "$app/navigation";
|
|
84 | 86 | geoSource = "file",
|
85 | 87 | tileSource = "http://localhost:8080/{z}/{x}/{y}.pbf",
|
86 | 88 | paintObject,
|
| 89 | + geojsonPromoteId = "areanm", |
| 90 | + vectorMetricProperty = "Index of Multiple Deprivation (IMD) Rank", |
| 91 | + vectorLayerName = "LSOA", |
| 92 | + borderColor = "#003300", |
| 93 | + labelSourceLayer = "place", |
87 | 94 | }: {
|
88 | 95 | data: object[];
|
89 | 96 | paintObject?: object;
|
|
130 | 137 | onidle?: (e: maplibregl.MapLibreEvent) => void;
|
131 | 138 | geoSource: "file" | "tiles" | "none";
|
132 | 139 | tileSource?: string;
|
| 140 | + geojsonPromoteId?: string; |
| 141 | + vectorMetricProperty?: string; |
| 142 | + vectorLayerName?: string; |
| 143 | + borderColor?: string; |
| 144 | + labelSourceLayer?: string; |
| 145 | + usingExternalData: false; |
133 | 146 | } = $props();
|
134 | 147 |
|
| 148 | + let usingExternalData = false; |
| 149 | + const tileSourceId = "lsoas"; |
| 150 | + const promoteProperty = "LSOA21NM"; |
| 151 | +
|
135 | 152 | let styleLookup = {
|
136 | 153 | "Carto-light":
|
137 | 154 | "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
|
|
163 | 180 | );
|
164 | 181 |
|
165 | 182 | let filteredGeoJsonData = $derived(filterGeo(geojsonData, year));
|
| 183 | + $inspect(breakCount); |
166 | 184 |
|
167 | 185 | let fillColors: string[] = $derived(
|
168 | 186 | setCustomPalette == true
|
|
172 | 190 |
|
173 | 191 | let tooFewColors = $derived(fillColors.length < breakCount);
|
174 | 192 |
|
| 193 | + let paint = $derived(() => { |
| 194 | + if (!map || !loaded) return; |
| 195 | +
|
| 196 | + const values = extractVectorMetricValues( |
| 197 | + map, |
| 198 | + vectorLayerName, |
| 199 | + vectorMetricProperty, |
| 200 | + ); |
| 201 | +
|
| 202 | + if (!values || values.length === 0) return; |
| 203 | +
|
| 204 | + let breaks: number[]; |
| 205 | +
|
| 206 | + if (breaksType === "quantile") { |
| 207 | + breaks = quantileBreaks(values, breakCount); |
| 208 | + } else if (breaksType === "jenks") { |
| 209 | + breaks = jenksBreaks(values, breakCount); |
| 210 | + } else { |
| 211 | + const min = Math.min(...values); |
| 212 | + const max = Math.max(...values); |
| 213 | + const step = (max - min) / breakCount; |
| 214 | + breaks = Array.from( |
| 215 | + { length: breakCount }, |
| 216 | + (_, i) => min + step * (i + 1), |
| 217 | + ); |
| 218 | + } |
| 219 | +
|
| 220 | + const paint = createPaintObjectFromMetric( |
| 221 | + vectorMetricProperty, |
| 222 | + breaks, |
| 223 | + fillColors, |
| 224 | + fillOpacity, |
| 225 | + ); |
| 226 | +
|
| 227 | + map.setPaintProperty(vectorLayerName, "fill-color", paint["fill-color"]); |
| 228 | + map.setPaintProperty( |
| 229 | + vectorLayerName, |
| 230 | + "fill-opacity", |
| 231 | + paint["fill-opacity"], |
| 232 | + ); |
| 233 | + }); |
| 234 | +
|
175 | 235 | $effect(() => {
|
176 | 236 | if (tooFewColors) {
|
177 | 237 | console.warn("Too few colours for the number of breaks");
|
178 | 238 | }
|
179 | 239 | });
|
180 | 240 |
|
181 |
| - let borderColor = "#003300"; |
182 |
| -
|
183 | 241 | let map: maplibregl.Map | undefined = $state();
|
184 | 242 |
|
185 | 243 | let loaded = $state(false);
|
|
265 | 323 | ? quantileBreaks(vals, breakCount)
|
266 | 324 | : customBreaks,
|
267 | 325 | );
|
| 326 | + let vectorPaintObject = $derived( |
| 327 | + usingExternalData |
| 328 | + ? createPaintObjectFromMetric(metric, breaks, fillColors, fillOpacity) |
| 329 | + : createPaintObjectFromMetric( |
| 330 | + vectorMetricProperty, |
| 331 | + breaks, |
| 332 | + fillColors, |
| 333 | + fillOpacity, |
| 334 | + ), |
| 335 | + ); |
268 | 336 |
|
269 | 337 | let dataWithColor = $derived(
|
270 | 338 | filteredMapData.map((d) => {
|
|
385 | 453 | <ScaleControl position={scaleControlPosition} unit={scaleControlUnit} />
|
386 | 454 | {/if}
|
387 | 455 | {#if geoSource == "file"}
|
388 |
| - <GeoJSON id="areas" data={merged} promoteId="areanm"> |
| 456 | + <GeoJSON id="areas" data={merged} promoteId={geojsonPromoteId}> |
389 | 457 | <FillLayer
|
390 | 458 | paint={{
|
391 | 459 | "fill-color": ["coalesce", ["get", "color"], "lightgrey"],
|
|
423 | 491 | </GeoJSON>
|
424 | 492 | {:else if geoSource == "tiles"}
|
425 | 493 | <VectorTileSource
|
426 |
| - id={"lsoas"} |
427 |
| - promoteId={"LSOA21NM"} |
| 494 | + id={tileSourceId} |
| 495 | + promoteId={promoteProperty} |
428 | 496 | tiles={[tileSource]}
|
429 | 497 | >
|
430 | 498 | <FillLayer
|
431 |
| - paint={paintObject} |
432 |
| - sourceLayer={"LSOA"} |
433 |
| - onclick={interactive |
434 |
| - ? (e) => { |
435 |
| - console.log(e); |
436 |
| - return zoomToArea(e); |
437 |
| - } |
438 |
| - : undefined} |
| 499 | + paint={vectorPaintObject} |
| 500 | + sourceLayer={vectorLayerName} |
| 501 | + onclick={interactive ? zoomToArea : undefined} |
439 | 502 | onmousemove={interactive
|
440 | 503 | ? (e) => {
|
441 |
| - hoveredArea = e.features[0].id; |
442 |
| - hoveredAreaData = |
443 |
| - e.features[0].properties[ |
444 |
| - "Index of Multiple Deprivation (IMD) Rank" |
445 |
| - ]; |
446 |
| - currentMousePosition = e.event.point; |
| 504 | + if (e.features?.[0]) { |
| 505 | + hoveredArea = e.features[0].id; |
| 506 | + hoveredAreaData = |
| 507 | + e.features[0].properties[vectorMetricProperty]; |
| 508 | + currentMousePosition = e.event.point; |
| 509 | + } |
447 | 510 | }
|
448 | 511 | : undefined}
|
449 | 512 | onmouseleave={interactive
|
|
452 | 515 | hoveredAreaData = null;
|
453 | 516 | }
|
454 | 517 | : undefined}
|
455 |
| - ></FillLayer> |
| 518 | + /> |
456 | 519 | {#if showBorder}
|
457 | 520 | <LineLayer
|
458 | 521 | layout={{ "line-cap": "round", "line-join": "round" }}
|
|
466 | 529 | ),
|
467 | 530 | }}
|
468 | 531 | beforeLayerType="symbol"
|
469 |
| - sourceLayer={"LSOA"} |
| 532 | + sourceLayer={vectorLayerName} |
470 | 533 | />
|
471 | 534 | {/if}
|
472 | 535 | </VectorTileSource>
|
|
0 commit comments