solid-map-gl 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunk/BTR7SKE6.js +7 -0
- package/dist/chunk/N4NHJCAS.jsx +28 -0
- package/dist/{index.d.ts → index/index.d.ts} +185 -5
- package/dist/index/index.js +10 -0
- package/dist/{index.jsx → index/index.jsx} +563 -142
- package/dist/testing/index.d.ts +109 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.jsx +334 -0
- package/package.json +38 -22
- package/dist/index.js +0 -11
|
@@ -1,38 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MapProvider,
|
|
3
|
+
useMapContext
|
|
4
|
+
} from "../chunk/N4NHJCAS.jsx";
|
|
5
|
+
|
|
1
6
|
// src/components/MapGL/index.tsx
|
|
2
7
|
import {
|
|
3
8
|
createSignal,
|
|
4
|
-
createEffect
|
|
9
|
+
createEffect,
|
|
5
10
|
onMount,
|
|
6
11
|
onCleanup,
|
|
7
12
|
on
|
|
8
13
|
} from "solid-js";
|
|
9
14
|
import { isServer } from "solid-js/web";
|
|
10
15
|
|
|
11
|
-
// src/
|
|
12
|
-
import { createContext, useContext, createEffect } from "solid-js";
|
|
13
|
-
import { createStore } from "solid-js/store";
|
|
14
|
-
var defaultState = {
|
|
15
|
-
map: null,
|
|
16
|
-
mapLib: null,
|
|
17
|
-
isMapLibre: false,
|
|
18
|
-
constants: {},
|
|
19
|
-
themeVersion: 0
|
|
20
|
-
};
|
|
21
|
-
var MapContext = createContext([defaultState]);
|
|
22
|
-
var useMapContext = () => useContext(MapContext);
|
|
23
|
-
var MapProvider = (props) => {
|
|
24
|
-
const [state, setState] = createStore({ ...defaultState });
|
|
25
|
-
props.map && setState("map", props.map);
|
|
26
|
-
props.mapLib && setState("mapLib", props.mapLib);
|
|
27
|
-
setState("isMapLibre", !!props.isMapLibre);
|
|
28
|
-
setState("constants", props.constants || {});
|
|
29
|
-
setState("themeVersion", props.themeVersion || 0);
|
|
30
|
-
createEffect(() => setState("constants", props.constants || {}));
|
|
31
|
-
createEffect(() => setState("themeVersion", props.themeVersion || 0));
|
|
32
|
-
return <MapContext.Provider value={[state]}>{props.children}</MapContext.Provider>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// src/events.ts
|
|
16
|
+
// src/lib/events.ts
|
|
36
17
|
var mapEvents = [
|
|
37
18
|
"onMouseDown",
|
|
38
19
|
"onMouseUp",
|
|
@@ -111,7 +92,7 @@ var drawEvents = [
|
|
|
111
92
|
"onActionable"
|
|
112
93
|
];
|
|
113
94
|
|
|
114
|
-
// src/mapStyles.ts
|
|
95
|
+
// src/lib/mapStyles.ts
|
|
115
96
|
var mapBase = "mapbox://styles/mapbox";
|
|
116
97
|
var gitBase = "https://raw.githubusercontent.com/";
|
|
117
98
|
var gishub = "https://raw.githubusercontent.com/GIShub4/map-styles/main/";
|
|
@@ -229,6 +210,79 @@ var rasterStyleList = {
|
|
|
229
210
|
}
|
|
230
211
|
};
|
|
231
212
|
|
|
213
|
+
// src/components/MapGL/tilesSettled.ts
|
|
214
|
+
var nextFrame = () => new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
215
|
+
var hasActiveFadeTransition = (map) => {
|
|
216
|
+
try {
|
|
217
|
+
return !!map.style?.hasTransitions?.();
|
|
218
|
+
} catch {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
function pollTilesLoaded(map, timeout) {
|
|
223
|
+
return new Promise((resolve) => {
|
|
224
|
+
const deadline = Date.now() + timeout;
|
|
225
|
+
const poll = () => {
|
|
226
|
+
if (map.areTilesLoaded()) {
|
|
227
|
+
resolve(true);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (Date.now() >= deadline) {
|
|
231
|
+
resolve(false);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
setTimeout(poll, 100);
|
|
235
|
+
};
|
|
236
|
+
poll();
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async function settleAfterIdle(map, options = {}) {
|
|
240
|
+
const { timeout = 1e4, fadeMargin = 400 } = options;
|
|
241
|
+
await pollTilesLoaded(map, timeout);
|
|
242
|
+
map.triggerRepaint();
|
|
243
|
+
await nextFrame();
|
|
244
|
+
await nextFrame();
|
|
245
|
+
if (fadeMargin > 0) {
|
|
246
|
+
const fadeDeadline = Date.now() + Math.max(fadeMargin, 2e3);
|
|
247
|
+
while (hasActiveFadeTransition(map) && Date.now() < fadeDeadline) {
|
|
248
|
+
map.triggerRepaint();
|
|
249
|
+
await nextFrame();
|
|
250
|
+
}
|
|
251
|
+
await new Promise((resolve) => setTimeout(resolve, fadeMargin));
|
|
252
|
+
map.triggerRepaint();
|
|
253
|
+
await nextFrame();
|
|
254
|
+
await nextFrame();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function waitForIdleAndSettle(map, options = {}) {
|
|
258
|
+
return new Promise((resolve) => {
|
|
259
|
+
map.once("idle", () => {
|
|
260
|
+
settleAfterIdle(map, options).then(resolve);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
function disableRasterFade(map) {
|
|
265
|
+
for (const layer of map.getStyle()?.layers ?? []) {
|
|
266
|
+
try {
|
|
267
|
+
map.setPaintProperty(layer.id, "raster-fade-duration", 0);
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/components/MapGL/offscreenCapture.ts
|
|
274
|
+
function createCapturer(map, settleOptions) {
|
|
275
|
+
return {
|
|
276
|
+
map,
|
|
277
|
+
waitUntilSettled: () => waitForIdleAndSettle(map, settleOptions),
|
|
278
|
+
capture: (type = "image/jpeg", quality = 0.92) => map.getCanvas().toDataURL(type, quality),
|
|
279
|
+
captureWhenSettled: async (type = "image/jpeg", quality = 0.92) => {
|
|
280
|
+
await waitForIdleAndSettle(map, settleOptions);
|
|
281
|
+
return map.getCanvas().toDataURL(type, quality);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
232
286
|
// src/components/MapGL/index.tsx
|
|
233
287
|
var MapGL = (props) => {
|
|
234
288
|
let map;
|
|
@@ -237,6 +291,7 @@ var MapGL = (props) => {
|
|
|
237
291
|
let mutationObserver;
|
|
238
292
|
let mapLib;
|
|
239
293
|
let isMapLibre = false;
|
|
294
|
+
let tilesLoadedGeneration = 0;
|
|
240
295
|
const [mapLoaded, setMapLoaded] = createSignal(null);
|
|
241
296
|
const [themeVersion, setThemeVersion] = createSignal(0);
|
|
242
297
|
const [darkMode, setDarkMode] = createSignal(
|
|
@@ -254,6 +309,14 @@ var MapGL = (props) => {
|
|
|
254
309
|
) || style : style;
|
|
255
310
|
};
|
|
256
311
|
onMount(async () => {
|
|
312
|
+
try {
|
|
313
|
+
await setupMap();
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.error("[MapGL] Failed to initialize map:", error);
|
|
316
|
+
props.onError?.(error);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
const setupMap = async () => {
|
|
257
320
|
mapLib = props.mapLib || await import("mapbox-gl");
|
|
258
321
|
if (!mapLib.Map) mapLib = window["maplibregl"] || window["mapboxgl"];
|
|
259
322
|
if (typeof mapLib.supported === "function" && !mapLib.supported())
|
|
@@ -269,7 +332,11 @@ var MapGL = (props) => {
|
|
|
269
332
|
projection: props.options?.projection,
|
|
270
333
|
container: mapRef,
|
|
271
334
|
style: getStyle(props.options?.style, props.darkStyle),
|
|
272
|
-
fitBoundsOptions: { padding: props.viewport?.padding }
|
|
335
|
+
fitBoundsOptions: { padding: props.viewport?.padding },
|
|
336
|
+
// Required for capture()/toDataURL() to read back anything from the canvas at all — forced
|
|
337
|
+
// regardless of `options` since getting this wrong doesn't degrade capture, it silently
|
|
338
|
+
// breaks it (an all-transparent/blank image, no error).
|
|
339
|
+
...props.offscreen ? { preserveDrawingBuffer: true } : {}
|
|
273
340
|
});
|
|
274
341
|
map.debug = props.debug;
|
|
275
342
|
map.debugEvents = props.debugEvents;
|
|
@@ -283,7 +350,7 @@ var MapGL = (props) => {
|
|
|
283
350
|
if (typeof prop === "function") {
|
|
284
351
|
map.on(event, (evt) => {
|
|
285
352
|
setTimeout(() => {
|
|
286
|
-
if (evt.clickOnLayer) return;
|
|
353
|
+
if (event === "click" && evt.clickOnLayer) return;
|
|
287
354
|
prop(evt);
|
|
288
355
|
props.debugEvents && debug(`Map '${event}' event:`, evt);
|
|
289
356
|
}, 0);
|
|
@@ -292,7 +359,7 @@ var MapGL = (props) => {
|
|
|
292
359
|
Object.keys(prop).forEach((layerId) => {
|
|
293
360
|
map.on(event, layerId, (evt) => {
|
|
294
361
|
setTimeout(() => {
|
|
295
|
-
if (evt.clickOnLayer) return;
|
|
362
|
+
if (event === "click" && evt.clickOnLayer) return;
|
|
296
363
|
prop[layerId](evt);
|
|
297
364
|
props.debugEvents && debug(`Map '${event}' event on '${layerId}':`, evt);
|
|
298
365
|
}, 0);
|
|
@@ -301,9 +368,30 @@ var MapGL = (props) => {
|
|
|
301
368
|
}
|
|
302
369
|
}
|
|
303
370
|
});
|
|
371
|
+
if (props.onTilesLoaded) {
|
|
372
|
+
const timeout = props.tilesLoadedTimeout ?? 1e4;
|
|
373
|
+
const fadeMargin = props.tilesLoadedFadeMargin ?? 400;
|
|
374
|
+
map.on("idle", () => {
|
|
375
|
+
const generation = ++tilesLoadedGeneration;
|
|
376
|
+
settleAfterIdle(map, { timeout, fadeMargin }).then(() => {
|
|
377
|
+
if (generation !== tilesLoadedGeneration) return;
|
|
378
|
+
debug("Tiles settled");
|
|
379
|
+
props.onTilesLoaded();
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
}
|
|
304
383
|
map.once("load", () => {
|
|
305
384
|
setMapLoaded(map);
|
|
306
385
|
debug("Map loaded");
|
|
386
|
+
if (props.offscreen) {
|
|
387
|
+
if (props.offscreen.disableRasterFade !== false) disableRasterFade(map);
|
|
388
|
+
props.onCapturerReady?.(
|
|
389
|
+
createCapturer(map, {
|
|
390
|
+
timeout: props.tilesLoadedTimeout ?? 1e4,
|
|
391
|
+
fadeMargin: props.tilesLoadedFadeMargin ?? 400
|
|
392
|
+
})
|
|
393
|
+
);
|
|
394
|
+
}
|
|
307
395
|
["mousedown", "touchstart", "wheel"].forEach(
|
|
308
396
|
(event) => map.on(
|
|
309
397
|
event,
|
|
@@ -382,12 +470,12 @@ var MapGL = (props) => {
|
|
|
382
470
|
props.onViewportChange(viewport);
|
|
383
471
|
});
|
|
384
472
|
});
|
|
385
|
-
}
|
|
386
|
-
|
|
473
|
+
};
|
|
474
|
+
createEffect(
|
|
387
475
|
on(
|
|
388
476
|
() => props.viewport,
|
|
389
477
|
(vp) => {
|
|
390
|
-
if (props.id !== vp?.id) return;
|
|
478
|
+
if (!map || props.id !== vp?.id) return;
|
|
391
479
|
if (expectingOwnEcho) {
|
|
392
480
|
expectingOwnEcho = false;
|
|
393
481
|
return;
|
|
@@ -412,7 +500,7 @@ var MapGL = (props) => {
|
|
|
412
500
|
{ defer: true }
|
|
413
501
|
)
|
|
414
502
|
);
|
|
415
|
-
|
|
503
|
+
createEffect(() => {
|
|
416
504
|
const loadedMap = mapLoaded();
|
|
417
505
|
if (typeof loadedMap?.setConfigProperty !== "function") {
|
|
418
506
|
if (loadedMap && props.config && Object.keys(props.config).length) {
|
|
@@ -430,13 +518,13 @@ var MapGL = (props) => {
|
|
|
430
518
|
debug(`Set Config (${id}:${key}) to:`, value);
|
|
431
519
|
}
|
|
432
520
|
});
|
|
433
|
-
|
|
521
|
+
createEffect(() => {
|
|
434
522
|
const proj = props.options?.projection;
|
|
435
523
|
if (!map || !proj) return;
|
|
436
524
|
map.setProjection(proj);
|
|
437
525
|
debug("Set Projection to:", proj);
|
|
438
526
|
});
|
|
439
|
-
|
|
527
|
+
createEffect(() => {
|
|
440
528
|
const cur = props.cursorStyle;
|
|
441
529
|
if (!map || !cur) return;
|
|
442
530
|
map.getCanvas().style.cursor = cur;
|
|
@@ -451,7 +539,7 @@ var MapGL = (props) => {
|
|
|
451
539
|
});
|
|
452
540
|
return list;
|
|
453
541
|
};
|
|
454
|
-
|
|
542
|
+
createEffect((prev) => {
|
|
455
543
|
const style = getStyle(props.options?.style, props.darkStyle);
|
|
456
544
|
if (map?.isStyleLoaded() && prev !== style) {
|
|
457
545
|
const oldStyle = map.getStyle();
|
|
@@ -484,7 +572,7 @@ var MapGL = (props) => {
|
|
|
484
572
|
"showPadding",
|
|
485
573
|
"showOverdrawInspector"
|
|
486
574
|
].forEach((item) => {
|
|
487
|
-
|
|
575
|
+
createEffect(() => {
|
|
488
576
|
const prop = props[item];
|
|
489
577
|
if (!map || !prop) return;
|
|
490
578
|
map[item] = prop;
|
|
@@ -494,6 +582,7 @@ var MapGL = (props) => {
|
|
|
494
582
|
onCleanup(() => {
|
|
495
583
|
resizeObserver?.disconnect();
|
|
496
584
|
mutationObserver?.disconnect();
|
|
585
|
+
tilesLoadedGeneration++;
|
|
497
586
|
map?.remove();
|
|
498
587
|
debug("Map removed");
|
|
499
588
|
});
|
|
@@ -502,7 +591,14 @@ var MapGL = (props) => {
|
|
|
502
591
|
id={props.id}
|
|
503
592
|
class={props?.class}
|
|
504
593
|
classList={props?.classList}
|
|
505
|
-
style={
|
|
594
|
+
style={props.offscreen ? {
|
|
595
|
+
position: "fixed",
|
|
596
|
+
left: "-99999px",
|
|
597
|
+
top: "-99999px",
|
|
598
|
+
width: `${props.offscreen.width}px`,
|
|
599
|
+
height: `${props.offscreen.height}px`,
|
|
600
|
+
...props.style
|
|
601
|
+
} : { width: "100%", height: "100%", ...props.style }}
|
|
506
602
|
>
|
|
507
603
|
{mapLoaded() && <MapProvider
|
|
508
604
|
map={mapLoaded()}
|
|
@@ -520,13 +616,13 @@ var MapGL = (props) => {
|
|
|
520
616
|
// src/components/Source/index.tsx
|
|
521
617
|
import {
|
|
522
618
|
onCleanup as onCleanup2,
|
|
523
|
-
createEffect as
|
|
524
|
-
createContext
|
|
525
|
-
useContext
|
|
619
|
+
createEffect as createEffect2,
|
|
620
|
+
createContext,
|
|
621
|
+
useContext,
|
|
526
622
|
createUniqueId
|
|
527
623
|
} from "solid-js";
|
|
528
|
-
var SourceContext =
|
|
529
|
-
var useSourceId = () =>
|
|
624
|
+
var SourceContext = createContext();
|
|
625
|
+
var useSourceId = () => useContext(SourceContext);
|
|
530
626
|
var Source = (props) => {
|
|
531
627
|
const [ctx] = useMapContext();
|
|
532
628
|
props.id ??= createUniqueId();
|
|
@@ -558,14 +654,14 @@ var Source = (props) => {
|
|
|
558
654
|
debug("Add Source:", props.id);
|
|
559
655
|
switch (anySource().type) {
|
|
560
656
|
case "geojson":
|
|
561
|
-
|
|
657
|
+
createEffect2(() => {
|
|
562
658
|
const data = anySource().data;
|
|
563
659
|
ctx.map.getSource(props.id).setData(data || {});
|
|
564
660
|
debug("Update GeoJSON Data:", props.id);
|
|
565
661
|
});
|
|
566
662
|
break;
|
|
567
663
|
case "image":
|
|
568
|
-
|
|
664
|
+
createEffect2(() => {
|
|
569
665
|
const url = anySource().url;
|
|
570
666
|
const coords = anySource().coordinates;
|
|
571
667
|
ctx.map.getSource(props.id).updateImage(url, coords);
|
|
@@ -573,7 +669,7 @@ var Source = (props) => {
|
|
|
573
669
|
});
|
|
574
670
|
break;
|
|
575
671
|
case "vector":
|
|
576
|
-
|
|
672
|
+
createEffect2(() => {
|
|
577
673
|
const url = anySource().url;
|
|
578
674
|
const tiles = anySource().tiles;
|
|
579
675
|
const source = ctx.map.getSource(props.id);
|
|
@@ -582,7 +678,7 @@ var Source = (props) => {
|
|
|
582
678
|
});
|
|
583
679
|
break;
|
|
584
680
|
case "raster":
|
|
585
|
-
|
|
681
|
+
createEffect2(() => {
|
|
586
682
|
const src = lookup(anySource().url);
|
|
587
683
|
const source = ctx.map.getSource(props.id);
|
|
588
684
|
src.url ? source.setUrl(src.url) : source.setTiles(src.tiles);
|
|
@@ -605,12 +701,12 @@ var Source = (props) => {
|
|
|
605
701
|
// src/components/Layer/index.tsx
|
|
606
702
|
import {
|
|
607
703
|
onCleanup as onCleanup3,
|
|
608
|
-
createEffect as
|
|
704
|
+
createEffect as createEffect3,
|
|
609
705
|
createMemo,
|
|
610
706
|
createUniqueId as createUniqueId2
|
|
611
707
|
} from "solid-js";
|
|
612
708
|
|
|
613
|
-
// src/styles.ts
|
|
709
|
+
// src/components/Layer/styles.ts
|
|
614
710
|
var baseStyle = [
|
|
615
711
|
"id",
|
|
616
712
|
"type",
|
|
@@ -674,7 +770,7 @@ var layoutStyles = [
|
|
|
674
770
|
"text-writing-mode"
|
|
675
771
|
];
|
|
676
772
|
|
|
677
|
-
// src/colors.ts
|
|
773
|
+
// src/components/Layer/colors.ts
|
|
678
774
|
var probe;
|
|
679
775
|
var toRgbString = (cssColor) => {
|
|
680
776
|
probe ??= document.body.appendChild(document.createElement("div"));
|
|
@@ -707,8 +803,37 @@ var resolveColor = (value) => {
|
|
|
707
803
|
}
|
|
708
804
|
return value;
|
|
709
805
|
};
|
|
806
|
+
var toRgbaComponents = (value) => {
|
|
807
|
+
const rgb = toRgbString(resolveColor(value)) ?? value;
|
|
808
|
+
const match = rgb.match(/rgba?\(([^)]+)\)/i);
|
|
809
|
+
if (!match) return [0, 0, 0, 1];
|
|
810
|
+
const [r, g, b, a = 1] = match[1].split(",").map(Number);
|
|
811
|
+
return [r, g, b, a];
|
|
812
|
+
};
|
|
710
813
|
|
|
711
814
|
// src/components/Layer/index.tsx
|
|
815
|
+
var PULSE_DEFAULTS = {
|
|
816
|
+
property: "icon-halo-width",
|
|
817
|
+
from: 0,
|
|
818
|
+
to: 4,
|
|
819
|
+
duration: 1500,
|
|
820
|
+
waveform: "out"
|
|
821
|
+
};
|
|
822
|
+
var PULSE_RAMP_FRACTION = 0.75;
|
|
823
|
+
var easeOutQuad = (t) => 1 - (1 - t) * (1 - t);
|
|
824
|
+
var pulseShape = (elapsed, duration, waveform) => {
|
|
825
|
+
const phase = elapsed % duration / duration;
|
|
826
|
+
if (waveform === "in-out") return (1 - Math.cos(phase * Math.PI * 2)) / 2;
|
|
827
|
+
const ramp = Math.min(phase / PULSE_RAMP_FRACTION, 1);
|
|
828
|
+
return easeOutQuad(ramp);
|
|
829
|
+
};
|
|
830
|
+
var lerpColor = (from, to, t) => {
|
|
831
|
+
const r = Math.round(from[0] + (to[0] - from[0]) * t);
|
|
832
|
+
const g = Math.round(from[1] + (to[1] - from[1]) * t);
|
|
833
|
+
const b = Math.round(from[2] + (to[2] - from[2]) * t);
|
|
834
|
+
const a = from[3] + (to[3] - from[3]) * t;
|
|
835
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
836
|
+
};
|
|
712
837
|
var diff = (newProps = {}, prevProps = {}) => {
|
|
713
838
|
const keys = /* @__PURE__ */ new Set([...Object.keys(newProps), ...Object.keys(prevProps)]);
|
|
714
839
|
return [...keys].reduce((acc, key) => {
|
|
@@ -720,9 +845,16 @@ var diff = (newProps = {}, prevProps = {}) => {
|
|
|
720
845
|
}, []);
|
|
721
846
|
};
|
|
722
847
|
var newKey = (key, type) => (key.startsWith(type) || key.startsWith("icon") || key.startsWith("text") ? "" : type + "-") + key.replace(/[A-Z]/g, (s) => "-" + s.toLowerCase());
|
|
723
|
-
var
|
|
848
|
+
var misplacedTopLevelProps = ["slot", "filter", "visible", "beforeId", "beforeType"];
|
|
849
|
+
var resolveColor2 = (key, value) => {
|
|
850
|
+
if (!key.endsWith("color")) return value;
|
|
851
|
+
if (Array.isArray(value)) return value.map((v) => resolveColor2(key, v));
|
|
852
|
+
return typeof value === "string" ? resolveColor(value) : value;
|
|
853
|
+
};
|
|
724
854
|
var constantRef = /^@(.+)$/;
|
|
725
855
|
var resolveConstant = (key, value, constants, debug) => {
|
|
856
|
+
if (Array.isArray(value))
|
|
857
|
+
return value.map((v) => resolveConstant(key, v, constants, debug));
|
|
726
858
|
if (typeof value !== "string") return value;
|
|
727
859
|
const match = value.match(constantRef);
|
|
728
860
|
if (!match) return value;
|
|
@@ -743,6 +875,10 @@ var updateStyle = (oldStyle, constants = {}, debug = () => {
|
|
|
743
875
|
Object.entries(oldStyle).forEach(([key, value]) => {
|
|
744
876
|
if (baseStyle.includes(key)) style[key] = value;
|
|
745
877
|
else {
|
|
878
|
+
if (misplacedTopLevelProps.includes(key))
|
|
879
|
+
debug(
|
|
880
|
+
`"${key}" is a <Layer> prop, not a style property \u2014 belongs outside "style", not inside it. Treating it as a paint/layout property instead.`
|
|
881
|
+
);
|
|
746
882
|
const nk = newKey(key, oldStyle.type);
|
|
747
883
|
layoutStyles.includes(nk) ? layout[nk] = resolveConstant(nk, value, constants, debug) : paint[nk] = resolvePaint(nk, value);
|
|
748
884
|
}
|
|
@@ -774,7 +910,7 @@ var Layer = (props) => {
|
|
|
774
910
|
...updateStyle(props.style, ctx.constants, debug),
|
|
775
911
|
id: layerId,
|
|
776
912
|
source: sourceId,
|
|
777
|
-
// `slot` is Mapbox Standard-Style-only — MapLibre has no equivalent (see
|
|
913
|
+
// `slot` is Mapbox Standard-Style-only — MapLibre has no equivalent (see .claude/dev-notes.md)
|
|
778
914
|
...ctx.isMapLibre ? {} : { slot: props.slot || "" },
|
|
779
915
|
metadata: {
|
|
780
916
|
smg: { beforeType: props.beforeType, beforeId: props.beforeId }
|
|
@@ -789,13 +925,13 @@ var Layer = (props) => {
|
|
|
789
925
|
if (props[item]) {
|
|
790
926
|
const event = item.slice(2).toLowerCase();
|
|
791
927
|
ctx.map.on(event, layerId, (evt) => {
|
|
792
|
-
evt.clickOnLayer = true;
|
|
928
|
+
if (event === "click") evt.clickOnLayer = true;
|
|
793
929
|
props[item](evt);
|
|
794
930
|
ctx.map.debugEvents && debug(`Layer '${event}' event on '${layerId}':`, evt);
|
|
795
931
|
});
|
|
796
932
|
}
|
|
797
933
|
});
|
|
798
|
-
|
|
934
|
+
createEffect3((prev) => {
|
|
799
935
|
ctx.themeVersion;
|
|
800
936
|
const style = updateStyle(props.style, ctx.constants, debug);
|
|
801
937
|
if (style === prev) return;
|
|
@@ -814,7 +950,7 @@ var Layer = (props) => {
|
|
|
814
950
|
debug("Update Layer Style:", layerId);
|
|
815
951
|
return style;
|
|
816
952
|
}, updateStyle(props.style, ctx.constants, debug));
|
|
817
|
-
|
|
953
|
+
createEffect3((prev) => {
|
|
818
954
|
if (props.visible === prev) return;
|
|
819
955
|
ctx.map.setLayoutProperty(
|
|
820
956
|
layerId,
|
|
@@ -825,19 +961,20 @@ var Layer = (props) => {
|
|
|
825
961
|
debug(`Update Visibility (${layerId}):`, props.visible.toString());
|
|
826
962
|
return props.visible;
|
|
827
963
|
}, props.visible);
|
|
828
|
-
|
|
964
|
+
createEffect3((prev) => {
|
|
829
965
|
if (getBeforeId() === prev) return prev;
|
|
830
966
|
ctx.map.moveLayer(layerId, getBeforeId());
|
|
831
967
|
debug(`Update Layer Z-Index (${layerId}):`, getBeforeId());
|
|
832
968
|
return getBeforeId();
|
|
833
969
|
}, getBeforeId());
|
|
834
|
-
|
|
835
|
-
if (
|
|
836
|
-
|
|
837
|
-
ctx.map.setFilter(layerId, props.filter);
|
|
970
|
+
createEffect3((prev) => {
|
|
971
|
+
if (props.filter === prev) return prev;
|
|
972
|
+
if (prev === void 0 && !props.filter) return prev;
|
|
973
|
+
ctx.map.setFilter(layerId, props.filter ?? null);
|
|
838
974
|
debug(`Update Filter (${layerId}):`, props.filter);
|
|
839
|
-
|
|
840
|
-
|
|
975
|
+
return props.filter;
|
|
976
|
+
}, void 0);
|
|
977
|
+
createEffect3(async () => {
|
|
841
978
|
if (!props.featureState || props.featureState.id === null) return;
|
|
842
979
|
!ctx.map.isStyleLoaded() && await ctx.map.once("styledata");
|
|
843
980
|
ctx.map.removeFeatureState({
|
|
@@ -853,6 +990,52 @@ var Layer = (props) => {
|
|
|
853
990
|
props.featureState.state
|
|
854
991
|
);
|
|
855
992
|
});
|
|
993
|
+
createEffect3(() => {
|
|
994
|
+
if (!props.pulse) return;
|
|
995
|
+
const configs = props.pulse === true ? [{}] : Array.isArray(props.pulse) ? props.pulse : [props.pulse];
|
|
996
|
+
const resolved = configs.map((config) => {
|
|
997
|
+
const { property, from, to, duration, waveform } = {
|
|
998
|
+
...PULSE_DEFAULTS,
|
|
999
|
+
...config
|
|
1000
|
+
};
|
|
1001
|
+
const isColor = typeof from === "string" || typeof to === "string";
|
|
1002
|
+
const [a, b] = waveform === "in" ? [to, from] : [from, to];
|
|
1003
|
+
return {
|
|
1004
|
+
property,
|
|
1005
|
+
duration,
|
|
1006
|
+
waveform,
|
|
1007
|
+
isColor,
|
|
1008
|
+
fromNum: isColor ? 0 : a,
|
|
1009
|
+
toNum: isColor ? 0 : b,
|
|
1010
|
+
fromRgba: isColor ? toRgbaComponents(a) : null,
|
|
1011
|
+
toRgba: isColor ? toRgbaComponents(b) : null
|
|
1012
|
+
};
|
|
1013
|
+
});
|
|
1014
|
+
resolved.forEach((cfg) => {
|
|
1015
|
+
ctx.map.setPaintProperty(
|
|
1016
|
+
layerId,
|
|
1017
|
+
`${cfg.property}-transition`,
|
|
1018
|
+
{ duration: 0, delay: 0 },
|
|
1019
|
+
{ validate: false }
|
|
1020
|
+
);
|
|
1021
|
+
});
|
|
1022
|
+
const start = performance.now();
|
|
1023
|
+
let frameId;
|
|
1024
|
+
const loop = (now) => {
|
|
1025
|
+
const elapsed = now - start;
|
|
1026
|
+
resolved.forEach((cfg) => {
|
|
1027
|
+
const t = pulseShape(elapsed, cfg.duration, cfg.waveform);
|
|
1028
|
+
const value = cfg.isColor ? lerpColor(cfg.fromRgba, cfg.toRgba, t) : cfg.fromNum + (cfg.toNum - cfg.fromNum) * t;
|
|
1029
|
+
ctx.map.setPaintProperty(layerId, cfg.property, value, {
|
|
1030
|
+
validate: false
|
|
1031
|
+
});
|
|
1032
|
+
});
|
|
1033
|
+
frameId = window.requestAnimationFrame(loop);
|
|
1034
|
+
};
|
|
1035
|
+
frameId = window.requestAnimationFrame(loop);
|
|
1036
|
+
debug(`Start Pulse (${layerId}):`, props.pulse);
|
|
1037
|
+
onCleanup3(() => window.cancelAnimationFrame(frameId));
|
|
1038
|
+
});
|
|
856
1039
|
onCleanup3(() => ctx.map?.getLayer(layerId) && ctx.map?.removeLayer(layerId));
|
|
857
1040
|
return props.children;
|
|
858
1041
|
};
|
|
@@ -863,11 +1046,11 @@ import {
|
|
|
863
1046
|
createUniqueId as createUniqueId3,
|
|
864
1047
|
createSignal as createSignal2,
|
|
865
1048
|
onMount as onMount2,
|
|
866
|
-
createContext as
|
|
867
|
-
useContext as
|
|
1049
|
+
createContext as createContext2,
|
|
1050
|
+
useContext as useContext2
|
|
868
1051
|
} from "solid-js";
|
|
869
|
-
var LayerContext =
|
|
870
|
-
var useScene = () =>
|
|
1052
|
+
var LayerContext = createContext2();
|
|
1053
|
+
var useScene = () => useContext2(LayerContext);
|
|
871
1054
|
var Layer3D = (props) => {
|
|
872
1055
|
const [ctx] = useMapContext();
|
|
873
1056
|
const [scene, setScene] = createSignal2(null);
|
|
@@ -1007,10 +1190,10 @@ var Layer3D = (props) => {
|
|
|
1007
1190
|
};
|
|
1008
1191
|
|
|
1009
1192
|
// src/components/Atmosphere/index.tsx
|
|
1010
|
-
import { onCleanup as onCleanup5, createEffect as
|
|
1193
|
+
import { onCleanup as onCleanup5, createEffect as createEffect4 } from "solid-js";
|
|
1011
1194
|
var Atmosphere = (props) => {
|
|
1012
1195
|
const [ctx] = useMapContext();
|
|
1013
|
-
|
|
1196
|
+
createEffect4(() => {
|
|
1014
1197
|
if (ctx.isMapLibre) ctx.map.setSky?.(props.style || {});
|
|
1015
1198
|
else ctx.map.setFog(props.style || {});
|
|
1016
1199
|
});
|
|
@@ -1026,7 +1209,7 @@ var Atmosphere = (props) => {
|
|
|
1026
1209
|
|
|
1027
1210
|
// src/components/Terrain/index.tsx
|
|
1028
1211
|
import {
|
|
1029
|
-
createEffect as
|
|
1212
|
+
createEffect as createEffect5,
|
|
1030
1213
|
createUniqueId as createUniqueId4,
|
|
1031
1214
|
onCleanup as onCleanup6
|
|
1032
1215
|
} from "solid-js";
|
|
@@ -1043,7 +1226,7 @@ var Terrain = (props) => {
|
|
|
1043
1226
|
});
|
|
1044
1227
|
ctx.map.sourceIdList.push(sourceId);
|
|
1045
1228
|
}
|
|
1046
|
-
|
|
1229
|
+
createEffect5(() => {
|
|
1047
1230
|
ctx.map.setTerrain({
|
|
1048
1231
|
exaggeration: props.exaggeration || 1,
|
|
1049
1232
|
source: props?.source || sourceId
|
|
@@ -1054,13 +1237,13 @@ var Terrain = (props) => {
|
|
|
1054
1237
|
};
|
|
1055
1238
|
|
|
1056
1239
|
// src/components/Control/index.tsx
|
|
1057
|
-
import { createSignal as createSignal3, createEffect as
|
|
1240
|
+
import { createSignal as createSignal3, createEffect as createEffect7, splitProps, untrack } from "solid-js";
|
|
1058
1241
|
|
|
1059
1242
|
// src/lib/createMapControl.ts
|
|
1060
|
-
import { createEffect as
|
|
1243
|
+
import { createEffect as createEffect6, onCleanup as onCleanup7 } from "solid-js";
|
|
1061
1244
|
var useControlPosition = (control, position) => {
|
|
1062
1245
|
const [ctx] = useMapContext();
|
|
1063
|
-
|
|
1246
|
+
createEffect6(() => {
|
|
1064
1247
|
const c = control();
|
|
1065
1248
|
const pos = position?.();
|
|
1066
1249
|
if (!c) return;
|
|
@@ -1087,7 +1270,7 @@ var Control = (props) => {
|
|
|
1087
1270
|
["logo", ctx.mapLib.LogoControl],
|
|
1088
1271
|
["terrain", ctx.mapLib.TerrainControl]
|
|
1089
1272
|
]);
|
|
1090
|
-
|
|
1273
|
+
createEffect7(() => {
|
|
1091
1274
|
untrack(
|
|
1092
1275
|
() => control() && ctx.map.hasControl(control()) && ctx.map.removeControl(control())
|
|
1093
1276
|
);
|
|
@@ -1100,7 +1283,7 @@ var Control = (props) => {
|
|
|
1100
1283
|
};
|
|
1101
1284
|
|
|
1102
1285
|
// src/components/Marker/index.tsx
|
|
1103
|
-
import { onCleanup as onCleanup8, createEffect as
|
|
1286
|
+
import { onCleanup as onCleanup8, createEffect as createEffect8, splitProps as splitProps2 } from "solid-js";
|
|
1104
1287
|
var Marker = (props) => {
|
|
1105
1288
|
if (!props.lngLat) throw new Error("Marker - lngLat is required");
|
|
1106
1289
|
const [update, create_popup, create_marker] = splitProps2(
|
|
@@ -1112,7 +1295,7 @@ var Marker = (props) => {
|
|
|
1112
1295
|
let marker = null;
|
|
1113
1296
|
let popup = null;
|
|
1114
1297
|
const LNGLAT = update.lngLat;
|
|
1115
|
-
|
|
1298
|
+
createEffect8(() => {
|
|
1116
1299
|
if (!ctx.map) return;
|
|
1117
1300
|
popup?.remove();
|
|
1118
1301
|
popup = new ctx.mapLib.Popup({
|
|
@@ -1120,31 +1303,31 @@ var Marker = (props) => {
|
|
|
1120
1303
|
focusAfterOpen: false,
|
|
1121
1304
|
...create_popup.popup
|
|
1122
1305
|
}).on("open", () => create_popup.onOpen?.()).on("close", () => create_popup.onClose?.());
|
|
1123
|
-
|
|
1306
|
+
createEffect8(() => {
|
|
1124
1307
|
if (update.children === void 0) return;
|
|
1125
1308
|
typeof update.children === "string" ? popup?.setHTML(update.children) : popup?.setDOMContent(update.children);
|
|
1126
1309
|
marker?.setPopup(popup);
|
|
1127
1310
|
});
|
|
1128
|
-
|
|
1311
|
+
createEffect8(
|
|
1129
1312
|
() => update.showPopup !== popup?.isOpen() && marker?.togglePopup()
|
|
1130
1313
|
);
|
|
1131
1314
|
});
|
|
1132
|
-
|
|
1315
|
+
createEffect8(() => {
|
|
1133
1316
|
if (!ctx.map) return;
|
|
1134
1317
|
marker?.remove();
|
|
1135
1318
|
marker = new ctx.mapLib.Marker(create_marker.options).on("dragstart", () => create_marker.onDragStart?.()).on("dragend", () => create_marker.onDragEnd?.()).on("drag", () => create_marker.onDrag?.(marker?.getLngLat().toArray())).setPopup(popup).setLngLat(LNGLAT).addTo(ctx.map);
|
|
1136
|
-
|
|
1319
|
+
createEffect8(
|
|
1137
1320
|
() => update.showPopup !== popup?.isOpen() && marker?.togglePopup()
|
|
1138
1321
|
);
|
|
1139
1322
|
});
|
|
1140
|
-
|
|
1141
|
-
|
|
1323
|
+
createEffect8(() => marker?.setLngLat(update.lngLat));
|
|
1324
|
+
createEffect8(() => marker?.setDraggable(update.draggable));
|
|
1142
1325
|
onCleanup8(() => marker?.remove());
|
|
1143
1326
|
return null;
|
|
1144
1327
|
};
|
|
1145
1328
|
|
|
1146
1329
|
// src/components/Popup/index.tsx
|
|
1147
|
-
import { onCleanup as onCleanup9, createEffect as
|
|
1330
|
+
import { onCleanup as onCleanup9, createEffect as createEffect9, splitProps as splitProps3 } from "solid-js";
|
|
1148
1331
|
var Popup = (props) => {
|
|
1149
1332
|
if (!props.trackPointer && !props.lngLat)
|
|
1150
1333
|
throw new Error("Popup - lngLat or trackPointer is required");
|
|
@@ -1155,7 +1338,7 @@ var Popup = (props) => {
|
|
|
1155
1338
|
]);
|
|
1156
1339
|
const [ctx] = useMapContext();
|
|
1157
1340
|
let popup;
|
|
1158
|
-
|
|
1341
|
+
createEffect9(() => {
|
|
1159
1342
|
if (!ctx.map) return;
|
|
1160
1343
|
popup?.remove();
|
|
1161
1344
|
popup = new ctx.mapLib.Popup({
|
|
@@ -1163,10 +1346,10 @@ var Popup = (props) => {
|
|
|
1163
1346
|
focusAfterOpen: false,
|
|
1164
1347
|
...create.options
|
|
1165
1348
|
}).on("open", () => create.onOpen?.()).on("close", () => create.onClose?.()).addTo(ctx.map);
|
|
1166
|
-
|
|
1349
|
+
createEffect9(
|
|
1167
1350
|
() => update.trackPointer ? popup.trackPointer() : popup.setLngLat(update.lngLat)
|
|
1168
1351
|
);
|
|
1169
|
-
|
|
1352
|
+
createEffect9(
|
|
1170
1353
|
() => typeof update.children === "string" ? popup.setHTML(update.children) : popup.setDOMContent(update.children)
|
|
1171
1354
|
);
|
|
1172
1355
|
});
|
|
@@ -1178,27 +1361,162 @@ var Popup = (props) => {
|
|
|
1178
1361
|
import {
|
|
1179
1362
|
onCleanup as onCleanup10,
|
|
1180
1363
|
createSignal as createSignal4,
|
|
1181
|
-
createEffect as
|
|
1364
|
+
createEffect as createEffect10,
|
|
1182
1365
|
untrack as untrack2
|
|
1183
1366
|
} from "solid-js";
|
|
1367
|
+
|
|
1368
|
+
// src/components/Image/sdf.ts
|
|
1369
|
+
var INF = 1e20;
|
|
1370
|
+
var ALPHA_TABLE = new Float64Array(256);
|
|
1371
|
+
for (let i = 0; i < 256; i++) {
|
|
1372
|
+
const d = 0.5 - Math.pow(i / 255, 1 / 2.2);
|
|
1373
|
+
ALPHA_TABLE[i] = d * Math.abs(d);
|
|
1374
|
+
}
|
|
1375
|
+
ALPHA_TABLE[255] = -INF;
|
|
1376
|
+
function edt1d(grid, offset, stride, length2, f, v, z) {
|
|
1377
|
+
v[0] = 0;
|
|
1378
|
+
z[0] = -INF;
|
|
1379
|
+
z[1] = INF;
|
|
1380
|
+
f[0] = grid[offset];
|
|
1381
|
+
for (let q = 1, k = 0, s = 0; q < length2; q++) {
|
|
1382
|
+
f[q] = grid[offset + q * stride];
|
|
1383
|
+
const q2 = q * q;
|
|
1384
|
+
do {
|
|
1385
|
+
const r = v[k];
|
|
1386
|
+
s = (f[q] - f[r] + q2 - r * r) / (q - r) / 2;
|
|
1387
|
+
} while (s <= z[k] && --k > -1);
|
|
1388
|
+
k++;
|
|
1389
|
+
v[k] = q;
|
|
1390
|
+
z[k] = s;
|
|
1391
|
+
z[k + 1] = INF;
|
|
1392
|
+
}
|
|
1393
|
+
for (let q = 0, k = 0; q < length2; q++) {
|
|
1394
|
+
while (z[k + 1] < q) k++;
|
|
1395
|
+
const r = v[k];
|
|
1396
|
+
const qr = q - r;
|
|
1397
|
+
grid[offset + q * stride] = f[r] + qr * qr;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function edt(data, width, height, f, v, z) {
|
|
1401
|
+
for (let x = 0; x < width; x++) edt1d(data, x, width, height, f, v, z);
|
|
1402
|
+
for (let y = 0; y < height; y++) edt1d(data, y * width, 1, width, f, v, z);
|
|
1403
|
+
}
|
|
1404
|
+
var sdfPadding = ({ radius = 8 } = {}) => Math.ceil(radius);
|
|
1405
|
+
function toSDF(imageData, { radius = 8, cutoff = 0.25 } = {}) {
|
|
1406
|
+
const { width, height } = imageData;
|
|
1407
|
+
const len = width * height;
|
|
1408
|
+
const gridOuter = new Float64Array(len).fill(INF);
|
|
1409
|
+
const gridInner = new Float64Array(len);
|
|
1410
|
+
const size = Math.max(width, height);
|
|
1411
|
+
const f = new Float64Array(size);
|
|
1412
|
+
const v = new Uint16Array(size);
|
|
1413
|
+
const z = new Float64Array(size + 1);
|
|
1414
|
+
const src = imageData.data;
|
|
1415
|
+
for (let i = 0, j = 3; i < len; i++, j += 4) {
|
|
1416
|
+
const a = src[j];
|
|
1417
|
+
if (a === 0) continue;
|
|
1418
|
+
const t = ALPHA_TABLE[a];
|
|
1419
|
+
gridOuter[i] = Math.max(0, t);
|
|
1420
|
+
gridInner[i] = Math.max(0, -t);
|
|
1421
|
+
}
|
|
1422
|
+
edt(gridOuter, width, height, f, v, z);
|
|
1423
|
+
edt(gridInner, width, height, f, v, z);
|
|
1424
|
+
const scale = 255 / radius;
|
|
1425
|
+
const base = 255 * (1 - cutoff);
|
|
1426
|
+
const out = new Uint8ClampedArray(len * 4);
|
|
1427
|
+
for (let i = 0, j = 0; i < len; i++, j += 4) {
|
|
1428
|
+
const d = Math.sqrt(gridOuter[i]) - Math.sqrt(gridInner[i]);
|
|
1429
|
+
const value = Math.max(0, Math.min(255, Math.round(base - scale * d)));
|
|
1430
|
+
out[j] = out[j + 1] = out[j + 2] = 255;
|
|
1431
|
+
out[j + 3] = value;
|
|
1432
|
+
}
|
|
1433
|
+
return { width, height, data: out };
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
// src/components/Image/shapes.ts
|
|
1184
1437
|
var PATTERN = {
|
|
1185
1438
|
diagonal_l: { size: 20, path: "M20 0 0 20M-10 10 10-10M10 30 30 10" },
|
|
1186
1439
|
diagonal_r: { size: 20, path: "M0 0 20 20M30 10 10-10M10 30-10 10" },
|
|
1187
1440
|
horizontal: { size: 14, path: "M7 0V20" },
|
|
1188
1441
|
vertical: { size: 14, path: "M0 7H20" },
|
|
1442
|
+
// A single centered "+" per tile, tiling into a repeating grid of crosses — not to be
|
|
1443
|
+
// confused with `SYMBOL.cross` (a single bold "+" icon) below.
|
|
1189
1444
|
cross: { size: 18, path: "M9 0V18M0 9H18" },
|
|
1190
1445
|
hash: { size: 30, path: "M15 0 30 15 15 30 0 15Z" },
|
|
1191
1446
|
chevron_h: { size: 20, path: "M-5 5 0 10 10 0 20 10 25 5M0 30 10 20 20 30" },
|
|
1192
1447
|
chevron_v: { size: 20, path: "M5-5 10 0 0 10 10 20 5 25M25 15 20 10 25 5" },
|
|
1193
1448
|
square: { size: 20, path: "M8 8H12V12H8Z", fill: true },
|
|
1194
1449
|
hex: { size: 50, path: "M0 0V50L50 25ZM50 0V50L0 25ZM25 0V50" },
|
|
1450
|
+
// Two arcs swept almost all the way around (`A2.5 2.5 0 1 1 ...` to a point a hair past the
|
|
1451
|
+
// start) rather than a `<circle>`, since this path is later stroked/filled via `Path2D`,
|
|
1452
|
+
// which has no dedicated circle primitive. A single dot per tile — not to be confused with
|
|
1453
|
+
// `SYMBOL.circle` (a single full-bleed circle icon) below.
|
|
1195
1454
|
circle: {
|
|
1196
1455
|
size: 25,
|
|
1197
1456
|
path: "M8 10A2.5 2.5 0 118.01 10M18 15A2.5 2.5 0 1018.01 15",
|
|
1198
1457
|
fill: true
|
|
1199
|
-
}
|
|
1458
|
+
},
|
|
1459
|
+
// `horizontal` and `vertical` combined into one crossed-line tile.
|
|
1460
|
+
grid: { size: 20, path: "M10 0V20M0 10H20" },
|
|
1461
|
+
// Two rows of offset (running-bond) bricks per tile, so the offset continues correctly
|
|
1462
|
+
// when tiles stack — row two's joints fall at the quarter-points, not centered, to match
|
|
1463
|
+
// a real brick course rather than just checkerboarding.
|
|
1464
|
+
brick: {
|
|
1465
|
+
size: 40,
|
|
1466
|
+
path: "M0 0H40M0 20H40M0 40H40M0 0V20M20 0V20M40 0V20M10 20V40M30 20V40"
|
|
1467
|
+
},
|
|
1468
|
+
// Two wavy horizontal lines per tile (quadratic-bezier "hump" repeated via the `T` shorthand),
|
|
1469
|
+
// for the wave/water fill texture common in geologic and land-cover maps.
|
|
1470
|
+
wave: { size: 20, path: "M0 5Q5 0 10 5T20 5M0 15Q5 10 10 15T20 15" }
|
|
1200
1471
|
};
|
|
1201
1472
|
var patternList = Object.keys(PATTERN);
|
|
1473
|
+
var svg = (path) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke-linecap="round" stroke-linejoin="round">
|
|
1474
|
+
<path d="${path}" fill="#000" stroke="#000" stroke-width="3"/>
|
|
1475
|
+
</svg>`;
|
|
1476
|
+
var SYMBOL = {
|
|
1477
|
+
square: svg("M3,3 L21,3 L21,21 L3,21 Z"),
|
|
1478
|
+
// Two semicircular arcs sharing one center/radius, traced in the same direction both times
|
|
1479
|
+
// (the standard "circle via two arcs" trick). The requested `1,1` radius is far smaller than
|
|
1480
|
+
// half the 16-unit chord between the two points, so per the SVG spec it's scaled up to the
|
|
1481
|
+
// minimum radius that can still connect them (8, i.e. exactly a semicircle each) — the circle
|
|
1482
|
+
// ends up centered on the chord's midpoint (12,11), not on the literal "1".
|
|
1483
|
+
circle: svg("M 12 4 A 1 1 0 0 0 12 20 A 1 1 0 0 0 12 4 Z"),
|
|
1484
|
+
triangle: svg("M 12 2 L 22 19 H 2 Z"),
|
|
1485
|
+
diamond: svg("M 12 1 L 19 12 L 12 23 L 5 12 Z"),
|
|
1486
|
+
pentagon: svg("M12,3 L21,9 L17,19 L7,19 L3,9 Z"),
|
|
1487
|
+
hexagon: svg("M12,3 L20,7.5 L20,16.5 L12,21 L4,16.5 L4,7.5 Z"),
|
|
1488
|
+
// A square with corners cut at 2/7 of its side, the standard construction for a regular
|
|
1489
|
+
// octagon (stop-sign proportions) without resorting to trig.
|
|
1490
|
+
octagon: svg("M 8 3 Q 12 3.3 16 3 Q 18.3 5.7 21 8 Q 20.7 12 21 16 Q 18.3 18.3 16 21 Q 12 20.7 8 21 Q 5.8 18.2 3 16 Q 3.3 12 3 8 Q 5.7 5.7 8 3 Z"),
|
|
1491
|
+
cross: svg("M 10.5 3 h 3 v 7.5 h 7.5 v 3 h -7.5 v 7.5 h -3 v -7.5 h -7.5 v -3 h 7.5 Z"),
|
|
1492
|
+
// The same 12-point "+" as `cross` above, rotated 45° about the center.
|
|
1493
|
+
x: svg("M 18 4 L 20 6 L 14 12 L 20 18 L 18 20 L 12 14 L 6 20 L 4 18 L 10 12 L 4 6 L 6 4 L 12 10 Z"),
|
|
1494
|
+
// A regular 5-pointed star: outer vertices every 72° alternating with inner vertices every
|
|
1495
|
+
// 72° offset by 36° (inner radius ~40% of the outer radius, the usual ratio for a balanced star).
|
|
1496
|
+
star: svg("M12,3 L14,9 L20.5,9 L15.5,13 L17.5,19.5 L12,15.5 L6.5,19.5 L8.5,13 L3.5,9 L10,9 Z"),
|
|
1497
|
+
// Two circular lobes (centers 8.5,8 / 15.5,8, radius 4.5 apart enough to overlap) joined by
|
|
1498
|
+
// straight tangent lines down to a bottom point. The notch between the lobes is the two
|
|
1499
|
+
// circles' actual intersection point (computed, not eyeballed), so both arcs land on it
|
|
1500
|
+
// exactly with no seam.
|
|
1501
|
+
heart: svg("M 12 21 L 3 11 A 4.5 4.5 0 1 1 11 8 L 13 8 A 4.5 4.5 0 1 1 21 11 Z"),
|
|
1502
|
+
// A map-pin/teardrop: a circle (center 12,10, r6) with two lines tangent to it converging on a
|
|
1503
|
+
// point below, so the straight edges meet the round top without a kink — the tangent points
|
|
1504
|
+
// and angles come from `acos(r / distance-to-point)`, not eyeballing.
|
|
1505
|
+
pin: svg("M 12 21 L 7 11 A 6 6 0 0 1 12 2 A 6 6 0 0 1 17 11 Z"),
|
|
1506
|
+
// The same tangent-circle construction as `pin`, just with the circle bigger relative to how
|
|
1507
|
+
// far below it the point sits (r6/d11 there vs r7.5/d10.5 here) — a shorter, wider point on a
|
|
1508
|
+
// rounder body: "a circle with one pointy edge" rather than a full elongated marker.
|
|
1509
|
+
drop: svg("M 4 21 V 12 A 7.5 7.5 0 0 1 12 4 A 7.5 7.5 0 0 1 13 21 Z"),
|
|
1510
|
+
// A thick chevron/bracket built as a filled ribbon, not a stroked open line: the outer and
|
|
1511
|
+
// inner edges of a constant-width "V", offset perpendicular to each arm and mitered where the
|
|
1512
|
+
// arms meet (both at the outer point and the inner notch). Has to be a closed silhouette like
|
|
1513
|
+
// every other symbol here, since `sdf` only encodes a filled alpha shape, not a stroke.
|
|
1514
|
+
chevron: svg("M 8 4 L 14 12 L 8 20 H 5 L 11 12 L 5 4 Z")
|
|
1515
|
+
};
|
|
1516
|
+
var symbolList = Object.keys(SYMBOL);
|
|
1517
|
+
var wrapSymbolPath = (d) => svg(d);
|
|
1518
|
+
|
|
1519
|
+
// src/components/Image/index.tsx
|
|
1202
1520
|
var MGL_Image = (props) => {
|
|
1203
1521
|
const [ctx] = useMapContext();
|
|
1204
1522
|
const [size, setSize] = createSignal4({ width: 0, height: 0 });
|
|
@@ -1217,13 +1535,14 @@ var MGL_Image = (props) => {
|
|
|
1217
1535
|
ctx.map?.hasImage(props.id) && ctx.map?.removeImage(props.id);
|
|
1218
1536
|
debug("Remove Image:", props.id);
|
|
1219
1537
|
});
|
|
1220
|
-
|
|
1538
|
+
createEffect10(() => {
|
|
1221
1539
|
if (!props.id) throw new Error("Image - ID is required");
|
|
1222
|
-
if (!props.source && !props.pattern)
|
|
1223
|
-
throw new Error("Image - Image or
|
|
1540
|
+
if (!props.source && !props.pattern && !props.symbol)
|
|
1541
|
+
throw new Error("Image - Image, Pattern or Symbol is required");
|
|
1224
1542
|
const pixelRatio = Math.max(1, Math.round(window.devicePixelRatio || 2));
|
|
1225
|
-
const ops = props.pattern ? { pixelRatio, ...props.options } : props.options;
|
|
1226
|
-
|
|
1543
|
+
const ops = props.pattern ? { pixelRatio, ...props.options } : props.sdf ? { ...props.options, sdf: true } : props.options;
|
|
1544
|
+
const symbolSource = props.symbol && (SYMBOL[props.symbol] || (props.symbol.trimStart().startsWith("<svg") ? props.symbol : wrapSymbolPath(props.symbol)));
|
|
1545
|
+
_loadImage(props.source || symbolSource || _createPattern(props.pattern, pixelRatio), (data, autoPixelRatio) => {
|
|
1227
1546
|
const finalOps = autoPixelRatio ? { ...ops, pixelRatio: autoPixelRatio } : ops;
|
|
1228
1547
|
const { width, height } = data;
|
|
1229
1548
|
if (ctx.map && !ctx.map.hasImage(props.id))
|
|
@@ -1241,6 +1560,7 @@ var MGL_Image = (props) => {
|
|
|
1241
1560
|
});
|
|
1242
1561
|
});
|
|
1243
1562
|
const _loadImage = (image, callback) => {
|
|
1563
|
+
const sdfOpts = props.sdf ? typeof props.sdf === "object" ? props.sdf : {} : null;
|
|
1244
1564
|
if (typeof image == "string" && image?.trimStart().startsWith("<svg")) {
|
|
1245
1565
|
image = new DOMParser().parseFromString(image, "image/svg+xml").childNodes[0];
|
|
1246
1566
|
}
|
|
@@ -1263,24 +1583,43 @@ var MGL_Image = (props) => {
|
|
|
1263
1583
|
const img = new Image();
|
|
1264
1584
|
img.crossOrigin = "Anonymous";
|
|
1265
1585
|
img.onload = () => {
|
|
1266
|
-
const
|
|
1586
|
+
const minAxis = Math.min(img.width, img.height);
|
|
1587
|
+
const floorScale = minAxis > 0 ? Math.max(1, 50 / minAxis) : 1;
|
|
1267
1588
|
const pixelRatio = props.options?.pixelRatio ?? Math.max(1, Math.round(window.devicePixelRatio || 1));
|
|
1268
1589
|
const scale = floorScale * pixelRatio;
|
|
1590
|
+
const padding = sdfOpts ? sdfPadding(sdfOpts) * scale : 0;
|
|
1591
|
+
const drawWidth = Math.round(img.width * scale);
|
|
1592
|
+
const drawHeight = Math.round(img.height * scale);
|
|
1269
1593
|
const canvas = document.createElement("canvas");
|
|
1270
|
-
canvas.width =
|
|
1271
|
-
canvas.height =
|
|
1594
|
+
canvas.width = drawWidth + padding * 2;
|
|
1595
|
+
canvas.height = drawHeight + padding * 2;
|
|
1272
1596
|
const ctx2 = canvas.getContext("2d");
|
|
1273
1597
|
ctx2.imageSmoothingEnabled = true;
|
|
1274
|
-
ctx2.drawImage(img,
|
|
1598
|
+
ctx2.drawImage(img, padding, padding, drawWidth, drawHeight);
|
|
1599
|
+
const imageData2 = ctx2.getImageData(0, 0, canvas.width, canvas.height);
|
|
1275
1600
|
return callback(
|
|
1276
|
-
|
|
1277
|
-
|
|
1601
|
+
sdfOpts ? toSDF(imageData2, sdfOpts) : imageData2,
|
|
1602
|
+
scale
|
|
1278
1603
|
);
|
|
1279
1604
|
};
|
|
1280
1605
|
img.onerror = (event) => console.error(`[MapGL] Image "${props.id}" failed to load:`, event);
|
|
1281
1606
|
img.src = image.trimStart().startsWith("<svg") ? "data:image/svg+xml;charset=utf-8," + encodeURIComponent(image) : image;
|
|
1282
1607
|
} else {
|
|
1283
|
-
return callback(imageData);
|
|
1608
|
+
if (!sdfOpts) return callback(imageData);
|
|
1609
|
+
const { width, height } = imageData;
|
|
1610
|
+
const padding = sdfPadding(sdfOpts);
|
|
1611
|
+
const canvas = document.createElement("canvas");
|
|
1612
|
+
canvas.width = width + padding * 2;
|
|
1613
|
+
canvas.height = height + padding * 2;
|
|
1614
|
+
const c = canvas.getContext("2d");
|
|
1615
|
+
c.imageSmoothingEnabled = true;
|
|
1616
|
+
if ("data" in imageData) {
|
|
1617
|
+
c.putImageData(imageData, padding, padding);
|
|
1618
|
+
} else {
|
|
1619
|
+
c.drawImage(imageData, padding, padding, width, height);
|
|
1620
|
+
}
|
|
1621
|
+
const pixels = c.getImageData(0, 0, canvas.width, canvas.height);
|
|
1622
|
+
return callback(toSDF(pixels, sdfOpts));
|
|
1284
1623
|
}
|
|
1285
1624
|
});
|
|
1286
1625
|
};
|
|
@@ -1301,7 +1640,7 @@ var MGL_Image = (props) => {
|
|
|
1301
1640
|
this.ctx.fillStyle = pattern.background || "transparent";
|
|
1302
1641
|
this.ctx.fillRect(0, 0, p.size, p.size);
|
|
1303
1642
|
this.ctx.strokeStyle = this.ctx.fillStyle = pattern.color || "black";
|
|
1304
|
-
this.ctx.lineWidth = pattern.
|
|
1643
|
+
this.ctx.lineWidth = pattern.lineWidth || 1;
|
|
1305
1644
|
this.ctx.stroke(new Path2D(p.path));
|
|
1306
1645
|
if (p.fill) this.ctx.fill(new Path2D(p.path));
|
|
1307
1646
|
this.data = this.ctx.getImageData(0, 0, this.width, this.height).data;
|
|
@@ -1313,7 +1652,7 @@ var MGL_Image = (props) => {
|
|
|
1313
1652
|
};
|
|
1314
1653
|
|
|
1315
1654
|
// src/components/Camera/index.tsx
|
|
1316
|
-
import { createEffect as
|
|
1655
|
+
import { createEffect as createEffect11, onCleanup as onCleanup11, createSignal as createSignal5 } from "solid-js";
|
|
1317
1656
|
var lerp = (a, b, t) => a.map((_, idx) => (1 - t) * a[idx] + t * b[idx]);
|
|
1318
1657
|
var slerp = (a, b, t) => {
|
|
1319
1658
|
const dotProduct = a.map((_, idx) => a[idx] * b[idx]).reduce((m, n) => m + n);
|
|
@@ -1360,7 +1699,7 @@ var Camera = (props) => {
|
|
|
1360
1699
|
isReverse = !isReverse;
|
|
1361
1700
|
animationTime = isReverse ? animationTime - 1e-3 : animationTime + 1e-3;
|
|
1362
1701
|
};
|
|
1363
|
-
|
|
1702
|
+
createEffect11(() => {
|
|
1364
1703
|
props.translate && window.requestAnimationFrame(frame);
|
|
1365
1704
|
});
|
|
1366
1705
|
const options = { duration: 1e3, easing: (n) => n };
|
|
@@ -1395,7 +1734,7 @@ var Camera = (props) => {
|
|
|
1395
1734
|
const onEnd = () => props.rotateGlobe ? rotateGlobe() : rotateViewport();
|
|
1396
1735
|
ctx.map.on("moveend", onEnd).on("dragend", onEnd);
|
|
1397
1736
|
let originalCenter;
|
|
1398
|
-
|
|
1737
|
+
createEffect11(() => {
|
|
1399
1738
|
if (props.rotateGlobe == void 0) return;
|
|
1400
1739
|
if (props.rotateGlobe) {
|
|
1401
1740
|
originalCenter = ctx.map.getCenter();
|
|
@@ -1404,7 +1743,7 @@ var Camera = (props) => {
|
|
|
1404
1743
|
props.resetWhenStopped ? ctx.map.stop().easeTo({ center: originalCenter }) : ctx.map.stop();
|
|
1405
1744
|
}
|
|
1406
1745
|
});
|
|
1407
|
-
|
|
1746
|
+
createEffect11(() => {
|
|
1408
1747
|
if (props.rotateViewport == void 0) return;
|
|
1409
1748
|
props.rotateViewport ? rotateViewport() : props.resetWhenStopped ? ctx.map.stop().resetNorthPitch() : ctx.map.stop();
|
|
1410
1749
|
});
|
|
@@ -1413,10 +1752,10 @@ var Camera = (props) => {
|
|
|
1413
1752
|
};
|
|
1414
1753
|
|
|
1415
1754
|
// src/components/Light/index.tsx
|
|
1416
|
-
import { onCleanup as onCleanup12, createEffect as
|
|
1755
|
+
import { onCleanup as onCleanup12, createEffect as createEffect12 } from "solid-js";
|
|
1417
1756
|
var Light = (props) => {
|
|
1418
1757
|
const [ctx] = useMapContext();
|
|
1419
|
-
|
|
1758
|
+
createEffect12(() => ctx.map.setLight(props.style || {}));
|
|
1420
1759
|
onCleanup12(() => ctx.map?.setLight(null));
|
|
1421
1760
|
return null;
|
|
1422
1761
|
};
|
|
@@ -1452,11 +1791,105 @@ MultiPointMode.toDisplayFeatures = function(state, geojson, display) {
|
|
|
1452
1791
|
};
|
|
1453
1792
|
var multi_point_default = MultiPointMode;
|
|
1454
1793
|
|
|
1794
|
+
// src/components/Draw/modes/geo.ts
|
|
1795
|
+
var EARTH_RADIUS_KM = 6371.0088;
|
|
1796
|
+
var KM_PER_MILE = 1.609344;
|
|
1797
|
+
var EARTH_RADIUS_M = 6378137;
|
|
1798
|
+
function toRadians(deg) {
|
|
1799
|
+
return deg * Math.PI / 180;
|
|
1800
|
+
}
|
|
1801
|
+
function toDegrees(rad) {
|
|
1802
|
+
return rad * 180 / Math.PI;
|
|
1803
|
+
}
|
|
1804
|
+
function distance(from, to) {
|
|
1805
|
+
const dLat = toRadians(to[1] - from[1]);
|
|
1806
|
+
const dLng = toRadians(to[0] - from[0]);
|
|
1807
|
+
const lat1 = toRadians(from[1]);
|
|
1808
|
+
const lat2 = toRadians(to[1]);
|
|
1809
|
+
const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2;
|
|
1810
|
+
return EARTH_RADIUS_KM * 2 * Math.asin(Math.sqrt(a));
|
|
1811
|
+
}
|
|
1812
|
+
function length(coordinates, units = "kilometers") {
|
|
1813
|
+
let total = 0;
|
|
1814
|
+
for (let i = 1; i < coordinates.length; i++) {
|
|
1815
|
+
total += distance(coordinates[i - 1], coordinates[i]);
|
|
1816
|
+
}
|
|
1817
|
+
return units === "miles" ? total / KM_PER_MILE : total;
|
|
1818
|
+
}
|
|
1819
|
+
function midpoint(from, to) {
|
|
1820
|
+
const lat1 = toRadians(from[1]);
|
|
1821
|
+
const lon1 = toRadians(from[0]);
|
|
1822
|
+
const lat2 = toRadians(to[1]);
|
|
1823
|
+
const dLon = toRadians(to[0] - from[0]);
|
|
1824
|
+
const bx = Math.cos(lat2) * Math.cos(dLon);
|
|
1825
|
+
const by = Math.cos(lat2) * Math.sin(dLon);
|
|
1826
|
+
const lat3 = Math.atan2(
|
|
1827
|
+
Math.sin(lat1) + Math.sin(lat2),
|
|
1828
|
+
Math.sqrt((Math.cos(lat1) + bx) ** 2 + by ** 2)
|
|
1829
|
+
);
|
|
1830
|
+
const lon3 = lon1 + Math.atan2(by, Math.cos(lat1) + bx);
|
|
1831
|
+
return [toDegrees(lon3), toDegrees(lat3)];
|
|
1832
|
+
}
|
|
1833
|
+
function ringArea(ring) {
|
|
1834
|
+
const n = ring.length;
|
|
1835
|
+
if (n <= 2) return 0;
|
|
1836
|
+
let total = 0;
|
|
1837
|
+
for (let i = 0; i < n; i++) {
|
|
1838
|
+
let lower;
|
|
1839
|
+
let middle;
|
|
1840
|
+
let upper;
|
|
1841
|
+
if (i === n - 2) {
|
|
1842
|
+
lower = n - 2;
|
|
1843
|
+
middle = n - 1;
|
|
1844
|
+
upper = 0;
|
|
1845
|
+
} else if (i === n - 1) {
|
|
1846
|
+
lower = n - 1;
|
|
1847
|
+
middle = 0;
|
|
1848
|
+
upper = 1;
|
|
1849
|
+
} else {
|
|
1850
|
+
lower = i;
|
|
1851
|
+
middle = i + 1;
|
|
1852
|
+
upper = i + 2;
|
|
1853
|
+
}
|
|
1854
|
+
total += (toRadians(ring[upper][0]) - toRadians(ring[lower][0])) * Math.sin(toRadians(ring[middle][1]));
|
|
1855
|
+
}
|
|
1856
|
+
return total * EARTH_RADIUS_M * EARTH_RADIUS_M / 2;
|
|
1857
|
+
}
|
|
1858
|
+
function area(rings) {
|
|
1859
|
+
return rings.reduce((total, ring, i) => {
|
|
1860
|
+
const ringTotal = Math.abs(ringArea(ring));
|
|
1861
|
+
return i === 0 ? total + ringTotal : total - ringTotal;
|
|
1862
|
+
}, 0);
|
|
1863
|
+
}
|
|
1864
|
+
function centerOfMass(rings) {
|
|
1865
|
+
const ring = rings[0];
|
|
1866
|
+
let meanX = 0;
|
|
1867
|
+
let meanY = 0;
|
|
1868
|
+
for (const [x, y] of ring) {
|
|
1869
|
+
meanX += x;
|
|
1870
|
+
meanY += y;
|
|
1871
|
+
}
|
|
1872
|
+
meanX /= ring.length;
|
|
1873
|
+
meanY /= ring.length;
|
|
1874
|
+
let xSum = 0;
|
|
1875
|
+
let ySum = 0;
|
|
1876
|
+
let areaSum = 0;
|
|
1877
|
+
for (let i = 0; i < ring.length - 1; i++) {
|
|
1878
|
+
const x1 = ring[i][0] - meanX;
|
|
1879
|
+
const y1 = ring[i][1] - meanY;
|
|
1880
|
+
const x2 = ring[i + 1][0] - meanX;
|
|
1881
|
+
const y2 = ring[i + 1][1] - meanY;
|
|
1882
|
+
const cross = x1 * y2 - x2 * y1;
|
|
1883
|
+
xSum += (x1 + x2) * cross;
|
|
1884
|
+
ySum += (y1 + y2) * cross;
|
|
1885
|
+
areaSum += cross;
|
|
1886
|
+
}
|
|
1887
|
+
if (areaSum === 0) return [meanX, meanY];
|
|
1888
|
+
const factor = 1 / (3 * areaSum);
|
|
1889
|
+
return [meanX + xSum * factor, meanY + ySum * factor];
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1455
1892
|
// src/components/Draw/modes/measurements.ts
|
|
1456
|
-
import length from "@turf/length";
|
|
1457
|
-
import area from "@turf/area";
|
|
1458
|
-
import midpoint from "@turf/midpoint";
|
|
1459
|
-
import { centerOfMass } from "@turf/center-of-mass";
|
|
1460
1893
|
var getCoords = (coords) => {
|
|
1461
1894
|
return new Intl.NumberFormat(void 0, {
|
|
1462
1895
|
maximumFractionDigits: 5
|
|
@@ -1466,17 +1899,8 @@ var getCoords = (coords) => {
|
|
|
1466
1899
|
};
|
|
1467
1900
|
var getLength = (coordinates, meta) => {
|
|
1468
1901
|
const lengthValue = length(
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
properties: {},
|
|
1472
|
-
geometry: {
|
|
1473
|
-
type: "LineString",
|
|
1474
|
-
coordinates
|
|
1475
|
-
}
|
|
1476
|
-
},
|
|
1477
|
-
{
|
|
1478
|
-
units: window.navigator.language === "en-US" ? "miles" : "kilometers"
|
|
1479
|
-
}
|
|
1902
|
+
coordinates,
|
|
1903
|
+
window.navigator.language === "en-US" ? "miles" : "kilometers"
|
|
1480
1904
|
);
|
|
1481
1905
|
const label = window.navigator.language === "en-US" ? new Intl.NumberFormat(void 0, {
|
|
1482
1906
|
style: "unit",
|
|
@@ -1496,19 +1920,12 @@ var getLength = (coordinates, meta) => {
|
|
|
1496
1920
|
},
|
|
1497
1921
|
geometry: {
|
|
1498
1922
|
type: "Point",
|
|
1499
|
-
coordinates: midpoint(coordinates[0], coordinates[1])
|
|
1923
|
+
coordinates: midpoint(coordinates[0], coordinates[1])
|
|
1500
1924
|
}
|
|
1501
1925
|
};
|
|
1502
1926
|
};
|
|
1503
1927
|
var getArea = (coordinates, meta) => {
|
|
1504
|
-
const areaValue = area(
|
|
1505
|
-
type: "Feature",
|
|
1506
|
-
properties: {},
|
|
1507
|
-
geometry: {
|
|
1508
|
-
type: "Polygon",
|
|
1509
|
-
coordinates
|
|
1510
|
-
}
|
|
1511
|
-
});
|
|
1928
|
+
const areaValue = area(coordinates);
|
|
1512
1929
|
const areaLabel = window.navigator.language === "en-US" ? new Intl.NumberFormat(void 0, {
|
|
1513
1930
|
style: "unit",
|
|
1514
1931
|
maximumFractionDigits: 2,
|
|
@@ -1527,10 +1944,10 @@ var getArea = (coordinates, meta) => {
|
|
|
1527
1944
|
value: areaLabel,
|
|
1528
1945
|
...meta
|
|
1529
1946
|
},
|
|
1530
|
-
geometry:
|
|
1531
|
-
type: "
|
|
1532
|
-
coordinates
|
|
1533
|
-
}
|
|
1947
|
+
geometry: {
|
|
1948
|
+
type: "Point",
|
|
1949
|
+
coordinates: centerOfMass(coordinates)
|
|
1950
|
+
}
|
|
1534
1951
|
};
|
|
1535
1952
|
};
|
|
1536
1953
|
|
|
@@ -1624,7 +2041,6 @@ var polygon_default = (lib) => {
|
|
|
1624
2041
|
};
|
|
1625
2042
|
|
|
1626
2043
|
// src/components/Draw/modes/radius.ts
|
|
1627
|
-
import length2 from "@turf/length";
|
|
1628
2044
|
function createVertex(parentId, coordinates, path, selected) {
|
|
1629
2045
|
return {
|
|
1630
2046
|
type: "Feature",
|
|
@@ -1707,7 +2123,7 @@ var RadiusMode = (lib) => ({
|
|
|
1707
2123
|
state.line.removeCoordinate("0");
|
|
1708
2124
|
if (state.line.isValid()) {
|
|
1709
2125
|
const lineGeoJson = state.line.toGeoJSON();
|
|
1710
|
-
const radius = (
|
|
2126
|
+
const radius = (length(lineGeoJson.geometry.coordinates) * 1e3).toFixed(1);
|
|
1711
2127
|
const center = lineGeoJson.geometry.coordinates[0];
|
|
1712
2128
|
this.deleteFeature([state.line.id], { silent: true });
|
|
1713
2129
|
const point = this.newFeature({
|
|
@@ -1747,7 +2163,7 @@ var RadiusMode = (lib) => ({
|
|
|
1747
2163
|
display(
|
|
1748
2164
|
createGeoJSONCircle(
|
|
1749
2165
|
geojson.geometry.coordinates[0],
|
|
1750
|
-
|
|
2166
|
+
length(geojson.geometry.coordinates),
|
|
1751
2167
|
state.line.id
|
|
1752
2168
|
)
|
|
1753
2169
|
);
|
|
@@ -2373,7 +2789,7 @@ var Draw = (props) => {
|
|
|
2373
2789
|
};
|
|
2374
2790
|
|
|
2375
2791
|
// src/components/DeckOverlay/index.tsx
|
|
2376
|
-
import { createEffect as
|
|
2792
|
+
import { createEffect as createEffect13 } from "solid-js";
|
|
2377
2793
|
var DeckOverlay = (props) => {
|
|
2378
2794
|
const [ctx] = useMapContext();
|
|
2379
2795
|
let overlay;
|
|
@@ -2382,7 +2798,7 @@ var DeckOverlay = (props) => {
|
|
|
2382
2798
|
return overlay;
|
|
2383
2799
|
};
|
|
2384
2800
|
useControlPosition(control);
|
|
2385
|
-
|
|
2801
|
+
createEffect13(() => overlay?.setProps(props.props || {}));
|
|
2386
2802
|
return null;
|
|
2387
2803
|
};
|
|
2388
2804
|
export {
|
|
@@ -2401,8 +2817,13 @@ export {
|
|
|
2401
2817
|
Source,
|
|
2402
2818
|
Terrain,
|
|
2403
2819
|
MapGL as default,
|
|
2820
|
+
disableRasterFade,
|
|
2404
2821
|
patternList,
|
|
2822
|
+
settleAfterIdle,
|
|
2823
|
+
symbolList,
|
|
2824
|
+
toSDF,
|
|
2405
2825
|
useMapContext,
|
|
2406
2826
|
useScene,
|
|
2407
|
-
useSourceId
|
|
2827
|
+
useSourceId,
|
|
2828
|
+
waitForIdleAndSettle
|
|
2408
2829
|
};
|