@bitalltech-maplibre/core 1.0.3 → 1.0.5
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 +340 -297
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +366 -100
- package/dist/index.umd.js +1 -1
- package/dist/types/__tests__/radar-power-group.test.d.ts +1 -0
- package/dist/types/effects/index.d.ts +2 -0
- package/dist/types/effects/low-altitude.d.ts +441 -15
- package/dist/types/effects/radar-power-group.d.ts +89 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/map/create-map.d.ts +1 -2
- package/package.json +37 -37
- package/dist/types/effects/low-altitude/breach-alert.d.ts +0 -61
- package/dist/types/effects/low-altitude/breathing-circle.d.ts +0 -5
- package/dist/types/effects/low-altitude/coordinated-countermeasure.d.ts +0 -5
- package/dist/types/effects/low-altitude/countermeasure-beam.d.ts +0 -5
- package/dist/types/effects/low-altitude/defence-circle.d.ts +0 -5
- package/dist/types/effects/low-altitude/directional-pulse.d.ts +0 -6
- package/dist/types/effects/low-altitude/navigation-spoofing.d.ts +0 -6
- package/dist/types/effects/low-altitude/pulse-marker.d.ts +0 -5
- package/dist/types/effects/low-altitude/radar-sweep.d.ts +0 -5
- package/dist/types/effects/low-altitude/ring-pulse-marker.d.ts +0 -5
- package/dist/types/effects/low-altitude/sector-scan.d.ts +0 -5
- package/dist/types/effects/low-altitude/shared.d.ts +0 -67
- package/dist/types/effects/low-altitude/target-lock.d.ts +0 -4
- package/dist/types/effects/low-altitude/types.d.ts +0 -333
- package/dist/types/effects/low-altitude/visual.d.ts +0 -15
package/dist/index.esm.js
CHANGED
|
@@ -293,6 +293,273 @@ const createBeamGeometry = (options) => {
|
|
|
293
293
|
}
|
|
294
294
|
};
|
|
295
295
|
};
|
|
296
|
+
const EMPTY_FEATURE_COLLECTION = {
|
|
297
|
+
type: "FeatureCollection",
|
|
298
|
+
features: []
|
|
299
|
+
};
|
|
300
|
+
const createFeature$1 = (geometry, properties) => ({
|
|
301
|
+
type: "Feature",
|
|
302
|
+
geometry,
|
|
303
|
+
properties
|
|
304
|
+
});
|
|
305
|
+
const asOpacity = (value, fallback) => Math.max(0, Math.min(1, value ?? fallback));
|
|
306
|
+
const createRadarPowerFeatures = (radar) => {
|
|
307
|
+
var _a;
|
|
308
|
+
if (radar.visible === false) {
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
const color = radar.color ?? "#38ff4a";
|
|
312
|
+
const ringColor = radar.ringColor ?? color;
|
|
313
|
+
const ringCount = Math.max(0, Math.floor(radar.ringCount ?? 4));
|
|
314
|
+
const coreRadius = Math.max(20, radar.coreRadius ?? Math.min(160, radar.radius * 0.035));
|
|
315
|
+
const features = [];
|
|
316
|
+
if (radar.fillOpacity && radar.fillOpacity > 0) {
|
|
317
|
+
features.push(
|
|
318
|
+
createFeature$1(createCirclePolygon(radar.center, radar.radius), {
|
|
319
|
+
radarId: radar.id,
|
|
320
|
+
kind: "fill",
|
|
321
|
+
color: radar.fillColor ?? color,
|
|
322
|
+
opacity: asOpacity(radar.fillOpacity, 0)
|
|
323
|
+
})
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
for (let index = ringCount; index >= 1; index -= 1) {
|
|
327
|
+
const distance = radar.radius * index / ringCount;
|
|
328
|
+
features.push(
|
|
329
|
+
createFeature$1(createCircleLine(radar.center, distance), {
|
|
330
|
+
radarId: radar.id,
|
|
331
|
+
kind: "ring",
|
|
332
|
+
color: ringColor,
|
|
333
|
+
opacity: asOpacity(radar.ringOpacity, 0.95),
|
|
334
|
+
width: Math.max(0, radar.ringWidth ?? 2)
|
|
335
|
+
})
|
|
336
|
+
);
|
|
337
|
+
if (radar.showDistanceLabels !== false) {
|
|
338
|
+
const text = ((_a = radar.distanceLabelFormatter) == null ? void 0 : _a.call(radar, distance, index)) ?? `${Math.round(distance)}`;
|
|
339
|
+
[
|
|
340
|
+
{ bearing: 0, textAnchor: "bottom" },
|
|
341
|
+
{ bearing: 90, textAnchor: "left" },
|
|
342
|
+
{ bearing: 180, textAnchor: "top" },
|
|
343
|
+
{ bearing: 270, textAnchor: "right" }
|
|
344
|
+
].forEach((label) => {
|
|
345
|
+
features.push(
|
|
346
|
+
createFeature$1(
|
|
347
|
+
{
|
|
348
|
+
type: "Point",
|
|
349
|
+
coordinates: getDestination(radar.center, distance, label.bearing)
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
radarId: radar.id,
|
|
353
|
+
kind: "distance-label",
|
|
354
|
+
text,
|
|
355
|
+
textAnchor: label.textAnchor,
|
|
356
|
+
color: radar.distanceLabelColor ?? ringColor,
|
|
357
|
+
opacity: asOpacity(radar.distanceLabelOpacity, 0.92),
|
|
358
|
+
haloColor: radar.distanceLabelHaloColor ?? "rgba(15, 23, 42, 0.42)",
|
|
359
|
+
size: radar.distanceLabelSize ?? 12
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (radar.showCrosshair !== false) {
|
|
367
|
+
features.push(
|
|
368
|
+
createFeature$1(
|
|
369
|
+
{
|
|
370
|
+
type: "LineString",
|
|
371
|
+
coordinates: [
|
|
372
|
+
getDestination(radar.center, radar.radius, 180),
|
|
373
|
+
getDestination(radar.center, radar.radius, 0)
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
radarId: radar.id,
|
|
378
|
+
kind: "crosshair",
|
|
379
|
+
color: radar.crosshairColor ?? ringColor,
|
|
380
|
+
opacity: asOpacity(radar.crosshairOpacity, 0.5),
|
|
381
|
+
width: Math.max(0, radar.crosshairWidth ?? 1.4)
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
createFeature$1(
|
|
385
|
+
{
|
|
386
|
+
type: "LineString",
|
|
387
|
+
coordinates: [
|
|
388
|
+
getDestination(radar.center, radar.radius, 270),
|
|
389
|
+
getDestination(radar.center, radar.radius, 90)
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
radarId: radar.id,
|
|
394
|
+
kind: "crosshair",
|
|
395
|
+
color: radar.crosshairColor ?? ringColor,
|
|
396
|
+
opacity: asOpacity(radar.crosshairOpacity, 0.5),
|
|
397
|
+
width: Math.max(0, radar.crosshairWidth ?? 1.4)
|
|
398
|
+
}
|
|
399
|
+
)
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
features.push(
|
|
403
|
+
createFeature$1(createCirclePolygon(radar.center, coreRadius), {
|
|
404
|
+
radarId: radar.id,
|
|
405
|
+
kind: "core",
|
|
406
|
+
color: radar.coreColor ?? color,
|
|
407
|
+
opacity: asOpacity(radar.fillOpacity, 0)
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
return features;
|
|
411
|
+
};
|
|
412
|
+
const createRadarPowerData = (radars) => ({
|
|
413
|
+
type: "FeatureCollection",
|
|
414
|
+
features: radars.flatMap(createRadarPowerFeatures)
|
|
415
|
+
});
|
|
416
|
+
const createLayerDefinitions = (id) => {
|
|
417
|
+
const source = `${id}-source`;
|
|
418
|
+
const layers = [
|
|
419
|
+
{
|
|
420
|
+
id: `${id}-fill`,
|
|
421
|
+
type: "fill",
|
|
422
|
+
source,
|
|
423
|
+
filter: ["==", ["get", "kind"], "fill"],
|
|
424
|
+
paint: {
|
|
425
|
+
"fill-color": ["coalesce", ["get", "color"], "#38ff4a"],
|
|
426
|
+
"fill-opacity": ["coalesce", ["get", "opacity"], 0]
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
id: `${id}-core`,
|
|
431
|
+
type: "fill",
|
|
432
|
+
source,
|
|
433
|
+
filter: ["==", ["get", "kind"], "core"],
|
|
434
|
+
paint: {
|
|
435
|
+
"fill-color": ["coalesce", ["get", "color"], "#38ff4a"],
|
|
436
|
+
"fill-opacity": ["coalesce", ["get", "opacity"], 0]
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
id: `${id}-ring`,
|
|
441
|
+
type: "line",
|
|
442
|
+
source,
|
|
443
|
+
filter: ["==", ["get", "kind"], "ring"],
|
|
444
|
+
paint: {
|
|
445
|
+
"line-color": ["coalesce", ["get", "color"], "#38ff4a"],
|
|
446
|
+
"line-opacity": ["coalesce", ["get", "opacity"], 0.95],
|
|
447
|
+
"line-width": ["coalesce", ["get", "width"], 2]
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: `${id}-crosshair`,
|
|
452
|
+
type: "line",
|
|
453
|
+
source,
|
|
454
|
+
filter: ["==", ["get", "kind"], "crosshair"],
|
|
455
|
+
paint: {
|
|
456
|
+
"line-color": ["coalesce", ["get", "color"], "#38ff4a"],
|
|
457
|
+
"line-opacity": ["coalesce", ["get", "opacity"], 0.5],
|
|
458
|
+
"line-width": ["coalesce", ["get", "width"], 1.4]
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
id: `${id}-labels`,
|
|
463
|
+
type: "symbol",
|
|
464
|
+
source,
|
|
465
|
+
filter: ["==", ["get", "kind"], "distance-label"],
|
|
466
|
+
layout: {
|
|
467
|
+
"text-field": ["get", "text"],
|
|
468
|
+
"text-size": ["coalesce", ["get", "size"], 12],
|
|
469
|
+
"text-anchor": ["get", "textAnchor"],
|
|
470
|
+
"text-allow-overlap": true,
|
|
471
|
+
"text-ignore-placement": true
|
|
472
|
+
},
|
|
473
|
+
paint: {
|
|
474
|
+
"text-color": ["coalesce", ["get", "color"], "#38ff4a"],
|
|
475
|
+
"text-opacity": ["coalesce", ["get", "opacity"], 0.92],
|
|
476
|
+
"text-halo-color": ["coalesce", ["get", "haloColor"], "rgba(15, 23, 42, 0.42)"],
|
|
477
|
+
"text-halo-width": 1
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
];
|
|
481
|
+
return {
|
|
482
|
+
source,
|
|
483
|
+
layers
|
|
484
|
+
};
|
|
485
|
+
};
|
|
486
|
+
const removeLayerIfExists$1 = (map, id) => {
|
|
487
|
+
if (map.getLayer(id)) {
|
|
488
|
+
map.removeLayer(id);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
const removeSourceIfExists$1 = (map, id) => {
|
|
492
|
+
if (map.getSource(id)) {
|
|
493
|
+
map.removeSource(id);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
const addRadarPowerGroup = (map, options) => {
|
|
497
|
+
const { source, layers } = createLayerDefinitions(options.id);
|
|
498
|
+
let radars = [...options.radars ?? []];
|
|
499
|
+
let removed = false;
|
|
500
|
+
map.addSource(source, {
|
|
501
|
+
type: "geojson",
|
|
502
|
+
data: EMPTY_FEATURE_COLLECTION
|
|
503
|
+
});
|
|
504
|
+
layers.forEach((layer) => {
|
|
505
|
+
map.addLayer(layer, options.beforeId);
|
|
506
|
+
});
|
|
507
|
+
const sourceRef = map.getSource(source);
|
|
508
|
+
const layerIds = layers.map((layer) => layer.id);
|
|
509
|
+
const setGroupVisibility = (visible) => {
|
|
510
|
+
layerIds.forEach((layerId) => {
|
|
511
|
+
if (map.getLayer(layerId)) {
|
|
512
|
+
map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
const setData = (nextRadars) => {
|
|
517
|
+
if (removed) return;
|
|
518
|
+
radars = nextRadars.map((radar) => ({ ...radar }));
|
|
519
|
+
sourceRef.setData(createRadarPowerData(radars));
|
|
520
|
+
};
|
|
521
|
+
if (radars.length > 0) {
|
|
522
|
+
setData(radars);
|
|
523
|
+
}
|
|
524
|
+
if (options.visible === false) {
|
|
525
|
+
setGroupVisibility(false);
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
id: options.id,
|
|
529
|
+
sourceId: source,
|
|
530
|
+
layerIds,
|
|
531
|
+
setData,
|
|
532
|
+
updateRadar(id, nextOptions) {
|
|
533
|
+
const index = radars.findIndex((radar) => radar.id === id);
|
|
534
|
+
if (index < 0 || removed) return;
|
|
535
|
+
radars[index] = { ...radars[index], ...nextOptions, id };
|
|
536
|
+
sourceRef.setData(createRadarPowerData(radars));
|
|
537
|
+
},
|
|
538
|
+
setRadarVisible(id, visible) {
|
|
539
|
+
const radar = radars.find((item) => item.id === id);
|
|
540
|
+
if (!radar || removed) return;
|
|
541
|
+
radar.visible = visible;
|
|
542
|
+
sourceRef.setData(createRadarPowerData(radars));
|
|
543
|
+
},
|
|
544
|
+
removeRadar(id) {
|
|
545
|
+
if (removed) return;
|
|
546
|
+
radars = radars.filter((radar) => radar.id !== id);
|
|
547
|
+
sourceRef.setData(createRadarPowerData(radars));
|
|
548
|
+
},
|
|
549
|
+
show() {
|
|
550
|
+
if (!removed) setGroupVisibility(true);
|
|
551
|
+
},
|
|
552
|
+
hide() {
|
|
553
|
+
if (!removed) setGroupVisibility(false);
|
|
554
|
+
},
|
|
555
|
+
remove() {
|
|
556
|
+
if (removed) return;
|
|
557
|
+
removed = true;
|
|
558
|
+
[...layerIds].reverse().forEach((layerId) => removeLayerIfExists$1(map, layerId));
|
|
559
|
+
removeSourceIfExists$1(map, source);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
};
|
|
296
563
|
const createFeature = (geometry, properties) => ({
|
|
297
564
|
type: "Feature",
|
|
298
565
|
geometry,
|
|
@@ -549,87 +816,6 @@ const createPulseMarkerRender = (options) => {
|
|
|
549
816
|
}
|
|
550
817
|
};
|
|
551
818
|
};
|
|
552
|
-
const addPulseMarker = (map, options) => createManagedEffect(map, options, createPulseMarkerRender);
|
|
553
|
-
const createBreathingCircleData = (options, phase = 0) => {
|
|
554
|
-
const baseRadius = Math.max(1, options.radius ?? 90);
|
|
555
|
-
const minRadius = Math.max(1, options.minRadius ?? baseRadius * 0.78);
|
|
556
|
-
const maxRadius = Math.max(
|
|
557
|
-
minRadius,
|
|
558
|
-
options.maxRadius ?? baseRadius * 1.22
|
|
559
|
-
);
|
|
560
|
-
const progress = (1 - Math.cos(phase * Math.PI * 2)) / 2;
|
|
561
|
-
const currentRadius = minRadius + (maxRadius - minRadius) * progress;
|
|
562
|
-
const fillOpacity = options.fillOpacity ?? 0.28;
|
|
563
|
-
const minFillOpacity = options.minFillOpacity ?? fillOpacity * 0.46;
|
|
564
|
-
const strokeOpacity = options.strokeOpacity ?? 0.82;
|
|
565
|
-
const minStrokeOpacity = options.minStrokeOpacity ?? strokeOpacity * 0.38;
|
|
566
|
-
const inverseProgress = 1 - progress;
|
|
567
|
-
const features = [
|
|
568
|
-
createFeature(createCirclePolygon(options.center, currentRadius), {
|
|
569
|
-
kind: "breathing-fill",
|
|
570
|
-
opacity: minFillOpacity + (fillOpacity - minFillOpacity) * inverseProgress
|
|
571
|
-
})
|
|
572
|
-
];
|
|
573
|
-
if ((options.strokeWidth ?? 2) > 0) {
|
|
574
|
-
features.push(
|
|
575
|
-
createFeature(createCircleLine(options.center, currentRadius), {
|
|
576
|
-
kind: "breathing-stroke",
|
|
577
|
-
opacity: minStrokeOpacity + (strokeOpacity - minStrokeOpacity) * inverseProgress
|
|
578
|
-
})
|
|
579
|
-
);
|
|
580
|
-
}
|
|
581
|
-
return createFeatureCollection(features);
|
|
582
|
-
};
|
|
583
|
-
const createBreathingCircleRender = (options) => {
|
|
584
|
-
const color = options.color || "#1677ff";
|
|
585
|
-
const fillColor = options.fillColor || color;
|
|
586
|
-
const strokeColor = options.strokeColor || color;
|
|
587
|
-
const strokeWidth = Math.max(0, options.strokeWidth ?? 2);
|
|
588
|
-
return {
|
|
589
|
-
data: createBreathingCircleData(options),
|
|
590
|
-
layers: [
|
|
591
|
-
{
|
|
592
|
-
id: `${options.id}-breathing-fill`,
|
|
593
|
-
type: "fill",
|
|
594
|
-
filter: ["==", ["get", "kind"], "breathing-fill"],
|
|
595
|
-
paint: {
|
|
596
|
-
"fill-color": fillColor,
|
|
597
|
-
"fill-opacity": ["coalesce", ["get", "opacity"], options.fillOpacity ?? 0.28]
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
id: `${options.id}-breathing-stroke`,
|
|
602
|
-
type: "line",
|
|
603
|
-
filter: ["==", ["get", "kind"], "breathing-stroke"],
|
|
604
|
-
layout: {
|
|
605
|
-
"line-cap": "round",
|
|
606
|
-
"line-join": "round"
|
|
607
|
-
},
|
|
608
|
-
paint: {
|
|
609
|
-
"line-color": strokeColor,
|
|
610
|
-
"line-opacity": ["coalesce", ["get", "opacity"], options.strokeOpacity ?? 0.82],
|
|
611
|
-
"line-width": strokeWidth
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
],
|
|
615
|
-
startAnimation({ getOptions, setData }) {
|
|
616
|
-
const duration = Math.max(400, getOptions().duration ?? 1800);
|
|
617
|
-
const startTime = performance.now();
|
|
618
|
-
let frameId = 0;
|
|
619
|
-
const tick = (timestamp) => {
|
|
620
|
-
const currentOptions = getOptions();
|
|
621
|
-
const phase = (timestamp - startTime) % duration / duration;
|
|
622
|
-
setData(createBreathingCircleData(currentOptions, phase));
|
|
623
|
-
frameId = requestAnimationFrame(tick);
|
|
624
|
-
};
|
|
625
|
-
frameId = requestAnimationFrame(tick);
|
|
626
|
-
return () => {
|
|
627
|
-
cancelAnimationFrame(frameId);
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
};
|
|
632
|
-
const addBreathingCircle = (map, options) => createManagedEffect(map, options, createBreathingCircleRender);
|
|
633
819
|
const createRingPulseEffectData = (options, phase = 0) => {
|
|
634
820
|
const baseRadius = Math.max(16, options.radius ?? 110);
|
|
635
821
|
const pulseScale = Math.max(0, options.pulseScale ?? 0.16);
|
|
@@ -719,7 +905,85 @@ const createRingPulseMarkerRender = (options) => {
|
|
|
719
905
|
}
|
|
720
906
|
};
|
|
721
907
|
};
|
|
722
|
-
const
|
|
908
|
+
const createBreathingCircleData = (options, phase = 0) => {
|
|
909
|
+
const baseRadius = Math.max(1, options.radius ?? 90);
|
|
910
|
+
const minRadius = Math.max(1, options.minRadius ?? baseRadius * 0.78);
|
|
911
|
+
const maxRadius = Math.max(
|
|
912
|
+
minRadius,
|
|
913
|
+
options.maxRadius ?? baseRadius * 1.22
|
|
914
|
+
);
|
|
915
|
+
const progress = (1 - Math.cos(phase * Math.PI * 2)) / 2;
|
|
916
|
+
const currentRadius = minRadius + (maxRadius - minRadius) * progress;
|
|
917
|
+
const fillOpacity = options.fillOpacity ?? 0.28;
|
|
918
|
+
const minFillOpacity = options.minFillOpacity ?? fillOpacity * 0.46;
|
|
919
|
+
const strokeOpacity = options.strokeOpacity ?? 0.82;
|
|
920
|
+
const minStrokeOpacity = options.minStrokeOpacity ?? strokeOpacity * 0.38;
|
|
921
|
+
const inverseProgress = 1 - progress;
|
|
922
|
+
const features = [
|
|
923
|
+
createFeature(createCirclePolygon(options.center, currentRadius), {
|
|
924
|
+
kind: "breathing-fill",
|
|
925
|
+
opacity: minFillOpacity + (fillOpacity - minFillOpacity) * inverseProgress
|
|
926
|
+
})
|
|
927
|
+
];
|
|
928
|
+
if ((options.strokeWidth ?? 2) > 0) {
|
|
929
|
+
features.push(
|
|
930
|
+
createFeature(createCircleLine(options.center, currentRadius), {
|
|
931
|
+
kind: "breathing-stroke",
|
|
932
|
+
opacity: minStrokeOpacity + (strokeOpacity - minStrokeOpacity) * inverseProgress
|
|
933
|
+
})
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
return createFeatureCollection(features);
|
|
937
|
+
};
|
|
938
|
+
const createBreathingCircleRender = (options) => {
|
|
939
|
+
const color = options.color || "#1677ff";
|
|
940
|
+
const fillColor = options.fillColor || color;
|
|
941
|
+
const strokeColor = options.strokeColor || color;
|
|
942
|
+
const strokeWidth = Math.max(0, options.strokeWidth ?? 2);
|
|
943
|
+
return {
|
|
944
|
+
data: createBreathingCircleData(options),
|
|
945
|
+
layers: [
|
|
946
|
+
{
|
|
947
|
+
id: `${options.id}-breathing-fill`,
|
|
948
|
+
type: "fill",
|
|
949
|
+
filter: ["==", ["get", "kind"], "breathing-fill"],
|
|
950
|
+
paint: {
|
|
951
|
+
"fill-color": fillColor,
|
|
952
|
+
"fill-opacity": ["coalesce", ["get", "opacity"], options.fillOpacity ?? 0.28]
|
|
953
|
+
}
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
id: `${options.id}-breathing-stroke`,
|
|
957
|
+
type: "line",
|
|
958
|
+
filter: ["==", ["get", "kind"], "breathing-stroke"],
|
|
959
|
+
layout: {
|
|
960
|
+
"line-cap": "round",
|
|
961
|
+
"line-join": "round"
|
|
962
|
+
},
|
|
963
|
+
paint: {
|
|
964
|
+
"line-color": strokeColor,
|
|
965
|
+
"line-opacity": ["coalesce", ["get", "opacity"], options.strokeOpacity ?? 0.82],
|
|
966
|
+
"line-width": strokeWidth
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
],
|
|
970
|
+
startAnimation({ getOptions, setData }) {
|
|
971
|
+
const duration = Math.max(400, getOptions().duration ?? 1800);
|
|
972
|
+
const startTime = performance.now();
|
|
973
|
+
let frameId = 0;
|
|
974
|
+
const tick = (timestamp) => {
|
|
975
|
+
const currentOptions = getOptions();
|
|
976
|
+
const phase = (timestamp - startTime) % duration / duration;
|
|
977
|
+
setData(createBreathingCircleData(currentOptions, phase));
|
|
978
|
+
frameId = requestAnimationFrame(tick);
|
|
979
|
+
};
|
|
980
|
+
frameId = requestAnimationFrame(tick);
|
|
981
|
+
return () => {
|
|
982
|
+
cancelAnimationFrame(frameId);
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
};
|
|
723
987
|
const clamp$1 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
724
988
|
const parseColor = (color) => {
|
|
725
989
|
const value = color.trim();
|
|
@@ -948,7 +1212,6 @@ const createSectorScanRender = (options) => {
|
|
|
948
1212
|
} : void 0
|
|
949
1213
|
};
|
|
950
1214
|
};
|
|
951
|
-
const addSectorScan = (map, options) => createManagedEffect(map, options, createSectorScanRender);
|
|
952
1215
|
const createDirectionalPulseData = (options, leadingDistance) => {
|
|
953
1216
|
const radius = Math.max(40, options.radius);
|
|
954
1217
|
const direction = options.direction ?? 270;
|
|
@@ -1027,7 +1290,6 @@ const createDirectionalPulseRender = (options) => ({
|
|
|
1027
1290
|
};
|
|
1028
1291
|
} : void 0
|
|
1029
1292
|
});
|
|
1030
|
-
const addDirectionalPulse = (map, options) => createManagedEffect(map, options, createDirectionalPulseRender);
|
|
1031
1293
|
const hasRadarSweepGradient = (options) => {
|
|
1032
1294
|
var _a;
|
|
1033
1295
|
const colors = (_a = options.gradient) == null ? void 0 : _a.colors;
|
|
@@ -1206,6 +1468,8 @@ const createRadarSweepData = (options, angleOffset = 0) => {
|
|
|
1206
1468
|
const createRadarSweepRender = (options) => {
|
|
1207
1469
|
const useGradient = hasRadarSweepGradient(options);
|
|
1208
1470
|
const canvas = useGradient ? createRadarSweepCanvas() : void 0;
|
|
1471
|
+
const rotationSpeed = options.rotationSpeed ?? 36;
|
|
1472
|
+
const animated = rotationSpeed !== 0;
|
|
1209
1473
|
if (canvas) {
|
|
1210
1474
|
drawRadarSweepCanvas(canvas, options);
|
|
1211
1475
|
}
|
|
@@ -1237,7 +1501,7 @@ const createRadarSweepRender = (options) => {
|
|
|
1237
1501
|
options.center,
|
|
1238
1502
|
options.radius
|
|
1239
1503
|
),
|
|
1240
|
-
animate:
|
|
1504
|
+
animate: animated
|
|
1241
1505
|
}
|
|
1242
1506
|
}
|
|
1243
1507
|
] : void 0,
|
|
@@ -1282,7 +1546,7 @@ const createRadarSweepRender = (options) => {
|
|
|
1282
1546
|
}
|
|
1283
1547
|
}
|
|
1284
1548
|
],
|
|
1285
|
-
startAnimation({ getOptions, setData }) {
|
|
1549
|
+
startAnimation: animated ? ({ getOptions, setData }) => {
|
|
1286
1550
|
const startTime = performance.now();
|
|
1287
1551
|
let frameId = 0;
|
|
1288
1552
|
const tick = (timestamp) => {
|
|
@@ -1291,17 +1555,18 @@ const createRadarSweepRender = (options) => {
|
|
|
1291
1555
|
if (canvas) {
|
|
1292
1556
|
drawRadarSweepCanvas(canvas, currentOptions, angleOffset);
|
|
1293
1557
|
}
|
|
1294
|
-
|
|
1558
|
+
if (!useGradient) {
|
|
1559
|
+
setData(createRadarSweepData(currentOptions, angleOffset));
|
|
1560
|
+
}
|
|
1295
1561
|
frameId = requestAnimationFrame(tick);
|
|
1296
1562
|
};
|
|
1297
1563
|
frameId = requestAnimationFrame(tick);
|
|
1298
1564
|
return () => {
|
|
1299
1565
|
cancelAnimationFrame(frameId);
|
|
1300
1566
|
};
|
|
1301
|
-
}
|
|
1567
|
+
} : void 0
|
|
1302
1568
|
};
|
|
1303
1569
|
};
|
|
1304
|
-
const addRadarSweep = (map, options) => createManagedEffect(map, options, createRadarSweepRender);
|
|
1305
1570
|
const createDefenceCircleCanvas = () => {
|
|
1306
1571
|
const canvas = document.createElement("canvas");
|
|
1307
1572
|
canvas.width = 512;
|
|
@@ -1402,7 +1667,6 @@ const createDefenceCircleRender = (options) => {
|
|
|
1402
1667
|
]
|
|
1403
1668
|
};
|
|
1404
1669
|
};
|
|
1405
|
-
const addDefenceCircle = (map, options) => createManagedEffect(map, options, createDefenceCircleRender);
|
|
1406
1670
|
const createCountermeasureBeamData = (options, elapsed = 0) => {
|
|
1407
1671
|
const sourceWidth = Math.max(1, options.sourceWidth ?? 220);
|
|
1408
1672
|
const targetWidth = Math.max(1, options.targetWidth ?? 45);
|
|
@@ -1552,7 +1816,6 @@ const createCountermeasureBeamRender = (options) => {
|
|
|
1552
1816
|
}
|
|
1553
1817
|
};
|
|
1554
1818
|
};
|
|
1555
|
-
const addCountermeasureBeam = (map, options) => createManagedEffect(map, options, createCountermeasureBeamRender);
|
|
1556
1819
|
const getCoordinationColor = (type) => {
|
|
1557
1820
|
if (type === "detection") return "#38bdf8";
|
|
1558
1821
|
if (type === "command") return "#22d3ee";
|
|
@@ -1715,7 +1978,6 @@ const createCoordinatedCountermeasureRender = (options) => {
|
|
|
1715
1978
|
}
|
|
1716
1979
|
};
|
|
1717
1980
|
};
|
|
1718
|
-
const addCoordinatedCountermeasure = (map, options) => createManagedEffect(map, options, createCoordinatedCountermeasureRender);
|
|
1719
1981
|
const createNavigationSpoofingData = (options, elapsed = 0) => {
|
|
1720
1982
|
const features = [
|
|
1721
1983
|
createFeature(
|
|
@@ -1866,6 +2128,15 @@ const createNavigationSpoofingRender = (options) => {
|
|
|
1866
2128
|
}
|
|
1867
2129
|
};
|
|
1868
2130
|
};
|
|
2131
|
+
const addPulseMarker = (map, options) => createManagedEffect(map, options, createPulseMarkerRender);
|
|
2132
|
+
const addBreathingCircle = (map, options) => createManagedEffect(map, options, createBreathingCircleRender);
|
|
2133
|
+
const addRingPulseMarker = (map, options) => createManagedEffect(map, options, createRingPulseMarkerRender);
|
|
2134
|
+
const addSectorScan = (map, options) => createManagedEffect(map, options, createSectorScanRender);
|
|
2135
|
+
const addDirectionalPulse = (map, options) => createManagedEffect(map, options, createDirectionalPulseRender);
|
|
2136
|
+
const addRadarSweep = (map, options) => createManagedEffect(map, options, createRadarSweepRender);
|
|
2137
|
+
const addDefenceCircle = (map, options) => createManagedEffect(map, options, createDefenceCircleRender);
|
|
2138
|
+
const addCountermeasureBeam = (map, options) => createManagedEffect(map, options, createCountermeasureBeamRender);
|
|
2139
|
+
const addCoordinatedCountermeasure = (map, options) => createManagedEffect(map, options, createCoordinatedCountermeasureRender);
|
|
1869
2140
|
const addNavigationSpoofing = (map, options) => createManagedEffect(map, options, createNavigationSpoofingRender);
|
|
1870
2141
|
const addTargetLock = (map, initialOptions) => {
|
|
1871
2142
|
const effectId = initialOptions.id;
|
|
@@ -3882,17 +4153,11 @@ const resolveStyle = (style, tdtToken) => {
|
|
|
3882
4153
|
return style;
|
|
3883
4154
|
};
|
|
3884
4155
|
const createMap = (options) => {
|
|
3885
|
-
const { style, tdtToken,
|
|
3886
|
-
|
|
4156
|
+
const { style, tdtToken, ...mapOptions } = options;
|
|
4157
|
+
return new maplibregl.Map({
|
|
3887
4158
|
...mapOptions,
|
|
3888
4159
|
style: resolveStyle(style, tdtToken)
|
|
3889
4160
|
});
|
|
3890
|
-
if (projection) {
|
|
3891
|
-
map.on("style.load", () => {
|
|
3892
|
-
map.setProjection({ type: projection });
|
|
3893
|
-
});
|
|
3894
|
-
}
|
|
3895
|
-
return map;
|
|
3896
4161
|
};
|
|
3897
4162
|
export {
|
|
3898
4163
|
BASE_MAP_TYPES,
|
|
@@ -3908,6 +4173,7 @@ export {
|
|
|
3908
4173
|
addDirectionalPulse,
|
|
3909
4174
|
addNavigationSpoofing,
|
|
3910
4175
|
addPulseMarker,
|
|
4176
|
+
addRadarPowerGroup,
|
|
3911
4177
|
addRadarSweep,
|
|
3912
4178
|
addRingPulseMarker,
|
|
3913
4179
|
addSectorScan,
|