uni-leaflet 1.1.0 → 1.2.0
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 +304 -5
- package/UniLeafletMap.vue +433 -65
- package/app-render.js +897 -95
- package/engine/canvas-tile-engine.ts +694 -79
- package/engine/factory.ts +15 -0
- package/engine/h5-map-adapter.ts +894 -133
- package/index.ts +4 -0
- package/package.json +1 -1
- package/types.ts +95 -2
- package/utils/bounds.ts +264 -0
- package/utils/cluster.ts +158 -0
- package/utils/curve.ts +86 -0
- package/utils/geojson.ts +175 -0
- package/uni-leaflet-1.0.0.tgz +0 -0
package/UniLeafletMap.vue
CHANGED
|
@@ -49,52 +49,6 @@
|
|
|
49
49
|
</view>
|
|
50
50
|
</template>
|
|
51
51
|
|
|
52
|
-
<script lang="ts">
|
|
53
|
-
export default {
|
|
54
|
-
methods: {
|
|
55
|
-
onRender_MapMove(this: any, val: any) {
|
|
56
|
-
const center = val?.center || val;
|
|
57
|
-
const zoom = val?.zoom;
|
|
58
|
-
if (center) {
|
|
59
|
-
this.$emit('update:center', center);
|
|
60
|
-
this.$emit('move', { center, zoom });
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
onRender_MapMoveEnd(this: any, val: any) {
|
|
64
|
-
const center = val?.center || val;
|
|
65
|
-
const zoom = val?.zoom;
|
|
66
|
-
if (center) {
|
|
67
|
-
this.$emit('update:center', center);
|
|
68
|
-
this.$emit('moveend', { center, zoom });
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
onRender_MapZoom(this: any, z: any) {
|
|
72
|
-
this.$emit('update:zoom', z);
|
|
73
|
-
this.$emit('zoom', z);
|
|
74
|
-
},
|
|
75
|
-
onRender_MapZoomEnd(this: any, z: any) {
|
|
76
|
-
this.$emit('update:zoom', z);
|
|
77
|
-
this.$emit('zoomend', z);
|
|
78
|
-
},
|
|
79
|
-
onRender_MapClick(this: any, val: any) {
|
|
80
|
-
const latLng = val?.latLng || val;
|
|
81
|
-
const point = val?.point || { x: 0, y: 0 };
|
|
82
|
-
this.$emit('click', { latLng, point });
|
|
83
|
-
},
|
|
84
|
-
onRender_OverlayClick(this: any, val: any) {
|
|
85
|
-
this.$emit('overlay-click', val);
|
|
86
|
-
if (val && val.type === 'marker') this.$emit('marker-click', val.data);
|
|
87
|
-
if (val && val.type === 'polyline') this.$emit('polyline-click', val.data);
|
|
88
|
-
if (val && val.type === 'polygon') this.$emit('polygon-click', val.data);
|
|
89
|
-
if (val && val.type === 'circle') this.$emit('circle-click', val.data);
|
|
90
|
-
},
|
|
91
|
-
onRender_Ready(this: any) {
|
|
92
|
-
this.$emit('ready', this);
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
</script>
|
|
97
|
-
|
|
98
52
|
<script setup lang="ts">
|
|
99
53
|
import {
|
|
100
54
|
ref,
|
|
@@ -116,6 +70,13 @@ import type {
|
|
|
116
70
|
CircleOptions,
|
|
117
71
|
MapOverlays,
|
|
118
72
|
OverlayClickEvent,
|
|
73
|
+
FitBoundsOptions,
|
|
74
|
+
LatLngBoundsExpression,
|
|
75
|
+
MapBounds,
|
|
76
|
+
ClusterOptions,
|
|
77
|
+
ClusterGroup,
|
|
78
|
+
GeoJsonStyle,
|
|
79
|
+
GeoJsonStyleOptions,
|
|
119
80
|
} from './types';
|
|
120
81
|
import { createMapEngine } from './engine/factory';
|
|
121
82
|
|
|
@@ -168,6 +129,30 @@ const props = defineProps({
|
|
|
168
129
|
type: Object as PropType<MapOverlays>,
|
|
169
130
|
default: () => undefined,
|
|
170
131
|
},
|
|
132
|
+
enableCluster: {
|
|
133
|
+
type: Boolean,
|
|
134
|
+
default: false,
|
|
135
|
+
},
|
|
136
|
+
clusterRadius: {
|
|
137
|
+
type: Number,
|
|
138
|
+
default: 60,
|
|
139
|
+
},
|
|
140
|
+
clusterMaxZoom: {
|
|
141
|
+
type: Number,
|
|
142
|
+
default: 17,
|
|
143
|
+
},
|
|
144
|
+
clusterOptions: {
|
|
145
|
+
type: Object as PropType<ClusterOptions>,
|
|
146
|
+
default: () => undefined,
|
|
147
|
+
},
|
|
148
|
+
geojson: {
|
|
149
|
+
type: [Object, Array] as PropType<any>,
|
|
150
|
+
default: () => null,
|
|
151
|
+
},
|
|
152
|
+
geojsonStyle: {
|
|
153
|
+
type: [Object, Function] as PropType<GeoJsonStyle>,
|
|
154
|
+
default: () => undefined,
|
|
155
|
+
},
|
|
171
156
|
width: {
|
|
172
157
|
type: String,
|
|
173
158
|
default: '100%',
|
|
@@ -192,9 +177,11 @@ const emit = defineEmits<{
|
|
|
192
177
|
(e: 'zoomend', val: number): void;
|
|
193
178
|
(e: 'click', val: { latLng: LatLngTuple; point: Point }): void;
|
|
194
179
|
(e: 'marker-click', val: MarkerOptions): void;
|
|
180
|
+
(e: 'cluster-click', val: ClusterGroup): void;
|
|
195
181
|
(e: 'polyline-click', val: PolylineOptions): void;
|
|
196
182
|
(e: 'polygon-click', val: PolygonOptions): void;
|
|
197
183
|
(e: 'circle-click', val: CircleOptions): void;
|
|
184
|
+
(e: 'geojson-click', val: any): void;
|
|
198
185
|
(e: 'overlay-click', val: OverlayClickEvent): void;
|
|
199
186
|
}>();
|
|
200
187
|
|
|
@@ -208,6 +195,22 @@ let engine: IMapEngine | null = null;
|
|
|
208
195
|
let isInternalUpdating = false;
|
|
209
196
|
|
|
210
197
|
// Compute payload for renderjs on App-Plus
|
|
198
|
+
const fitBoundsAction = ref<{
|
|
199
|
+
bounds: any;
|
|
200
|
+
options?: FitBoundsOptions;
|
|
201
|
+
timestamp: number;
|
|
202
|
+
} | null>(null);
|
|
203
|
+
|
|
204
|
+
const geojsonRevision = ref(0);
|
|
205
|
+
|
|
206
|
+
watch(
|
|
207
|
+
[() => props.geojson, () => props.overlays?.geojson],
|
|
208
|
+
() => {
|
|
209
|
+
geojsonRevision.value++;
|
|
210
|
+
},
|
|
211
|
+
{ deep: true }
|
|
212
|
+
);
|
|
213
|
+
|
|
211
214
|
const mapPropsPayload = computed(() => ({
|
|
212
215
|
appMapId,
|
|
213
216
|
center: props.center,
|
|
@@ -222,6 +225,14 @@ const mapPropsPayload = computed(() => ({
|
|
|
222
225
|
polygons: props.polygons,
|
|
223
226
|
circles: props.circles,
|
|
224
227
|
overlays: props.overlays,
|
|
228
|
+
geojson: props.geojson,
|
|
229
|
+
geojsonStyle: props.geojsonStyle,
|
|
230
|
+
geojsonRevision: geojsonRevision.value,
|
|
231
|
+
enableCluster: props.enableCluster,
|
|
232
|
+
clusterRadius: props.clusterRadius,
|
|
233
|
+
clusterMaxZoom: props.clusterMaxZoom,
|
|
234
|
+
clusterOptions: props.clusterOptions,
|
|
235
|
+
fitBoundsAction: fitBoundsAction.value,
|
|
225
236
|
}));
|
|
226
237
|
|
|
227
238
|
// Touch & Mouse Wheel handlers for Canvas/Mini-program
|
|
@@ -332,29 +343,87 @@ watch(
|
|
|
332
343
|
}
|
|
333
344
|
);
|
|
334
345
|
|
|
335
|
-
// Overlays Watchers
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
346
|
+
// Overlays Watchers - Granular independent watches to prevent cross-layer invalidation
|
|
347
|
+
watch(
|
|
348
|
+
() => props.polygons,
|
|
349
|
+
(newPolygons) => {
|
|
350
|
+
if (!engine) return;
|
|
351
|
+
if (newPolygons !== undefined && typeof (engine as any).setPolygons === 'function') {
|
|
352
|
+
(engine as any).setPolygons(newPolygons);
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
{ deep: true }
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
watch(
|
|
359
|
+
() => props.polylines,
|
|
360
|
+
(newPolylines) => {
|
|
361
|
+
if (!engine) return;
|
|
362
|
+
if (newPolylines !== undefined && typeof (engine as any).setPolylines === 'function') {
|
|
363
|
+
(engine as any).setPolylines(newPolylines);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{ deep: true }
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
watch(
|
|
370
|
+
() => props.circles,
|
|
371
|
+
(newCircles) => {
|
|
372
|
+
if (!engine) return;
|
|
373
|
+
if (newCircles !== undefined && typeof (engine as any).setCircles === 'function') {
|
|
374
|
+
(engine as any).setCircles(newCircles);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
{ deep: true }
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
watch(
|
|
381
|
+
() => props.markers,
|
|
382
|
+
(newMarkers) => {
|
|
383
|
+
if (!engine) return;
|
|
384
|
+
if (newMarkers !== undefined && typeof (engine as any).setMarkers === 'function') {
|
|
385
|
+
(engine as any).setMarkers(newMarkers);
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
{ deep: true }
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
watch(
|
|
392
|
+
[() => props.geojson, () => props.geojsonStyle],
|
|
393
|
+
([newData, newStyle]) => {
|
|
394
|
+
if (!engine) return;
|
|
395
|
+
if (newData !== undefined && typeof (engine as any).setGeoJSON === 'function') {
|
|
396
|
+
(engine as any).setGeoJSON(newData, newStyle);
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
{ deep: true }
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
watch(
|
|
403
|
+
() => props.overlays,
|
|
404
|
+
(newOverlays) => {
|
|
405
|
+
if (!engine || !newOverlays) return;
|
|
406
|
+
engine.setOverlays(newOverlays);
|
|
407
|
+
},
|
|
408
|
+
{ deep: true }
|
|
409
|
+
);
|
|
347
410
|
|
|
348
411
|
watch(
|
|
349
412
|
[
|
|
350
|
-
() => props.
|
|
351
|
-
() => props.
|
|
352
|
-
() => props.
|
|
353
|
-
() => props.
|
|
354
|
-
() => props.circles,
|
|
413
|
+
() => props.enableCluster,
|
|
414
|
+
() => props.clusterRadius,
|
|
415
|
+
() => props.clusterMaxZoom,
|
|
416
|
+
() => props.clusterOptions,
|
|
355
417
|
],
|
|
356
418
|
() => {
|
|
357
|
-
|
|
419
|
+
const opts = props.clusterOptions || {
|
|
420
|
+
enable: props.enableCluster,
|
|
421
|
+
clusterRadius: props.clusterRadius,
|
|
422
|
+
clusterMaxZoom: props.clusterMaxZoom,
|
|
423
|
+
};
|
|
424
|
+
if (engine && typeof (engine as any).setClusterOptions === 'function') {
|
|
425
|
+
(engine as any).setClusterOptions(opts);
|
|
426
|
+
}
|
|
358
427
|
},
|
|
359
428
|
{ deep: true }
|
|
360
429
|
);
|
|
@@ -441,6 +510,7 @@ function onOverlayClick(event: OverlayClickEvent) {
|
|
|
441
510
|
if (event.type === 'polyline') emit('polyline-click', event.data as PolylineOptions);
|
|
442
511
|
if (event.type === 'polygon') emit('polygon-click', event.data as PolygonOptions);
|
|
443
512
|
if (event.type === 'circle') emit('circle-click', event.data as CircleOptions);
|
|
513
|
+
if (event.type === 'geojson') emit('geojson-click', event.data);
|
|
444
514
|
}
|
|
445
515
|
|
|
446
516
|
// Handler when renderjs is ready on App-Plus
|
|
@@ -457,6 +527,8 @@ onMounted(async () => {
|
|
|
457
527
|
if (props.polylines) initialOverlays.polylines = props.polylines;
|
|
458
528
|
if (props.polygons) initialOverlays.polygons = props.polygons;
|
|
459
529
|
if (props.circles) initialOverlays.circles = props.circles;
|
|
530
|
+
if (props.geojson) initialOverlays.geojson = props.geojson;
|
|
531
|
+
if (props.geojsonStyle) initialOverlays.geojsonStyle = props.geojsonStyle;
|
|
460
532
|
|
|
461
533
|
const commonOptions = {
|
|
462
534
|
center: props.center,
|
|
@@ -467,6 +539,8 @@ onMounted(async () => {
|
|
|
467
539
|
subdomains: props.subdomains,
|
|
468
540
|
layers: props.layers,
|
|
469
541
|
overlays: initialOverlays,
|
|
542
|
+
geojson: props.geojson,
|
|
543
|
+
geojsonStyle: props.geojsonStyle,
|
|
470
544
|
showControls: props.showControls,
|
|
471
545
|
onMove: onMapMove,
|
|
472
546
|
onMoveEnd: onMapMoveEnd,
|
|
@@ -474,6 +548,12 @@ onMounted(async () => {
|
|
|
474
548
|
onZoomEnd: onMapZoomEnd,
|
|
475
549
|
onClick: onMapClick,
|
|
476
550
|
onOverlayClick: onOverlayClick,
|
|
551
|
+
clusterOptions: props.clusterOptions || {
|
|
552
|
+
enable: props.enableCluster,
|
|
553
|
+
clusterRadius: props.clusterRadius,
|
|
554
|
+
clusterMaxZoom: props.clusterMaxZoom,
|
|
555
|
+
},
|
|
556
|
+
onClusterClick: (cluster: ClusterGroup) => emit('cluster-click', cluster),
|
|
477
557
|
};
|
|
478
558
|
|
|
479
559
|
// #ifdef H5
|
|
@@ -544,6 +624,102 @@ onUnmounted(() => {
|
|
|
544
624
|
});
|
|
545
625
|
|
|
546
626
|
|
|
627
|
+
function resolveTargetBounds(target: any) {
|
|
628
|
+
if (target === 'markers' || target === 'points') {
|
|
629
|
+
return props.markers || props.overlays?.markers || [];
|
|
630
|
+
}
|
|
631
|
+
if (target === 'polylines' || target === 'lines') {
|
|
632
|
+
return props.polylines || props.overlays?.polylines || [];
|
|
633
|
+
}
|
|
634
|
+
if (target === 'polygons') {
|
|
635
|
+
return props.polygons || props.overlays?.polygons || [];
|
|
636
|
+
}
|
|
637
|
+
if (target === 'circles') {
|
|
638
|
+
return props.circles || props.overlays?.circles || [];
|
|
639
|
+
}
|
|
640
|
+
if (target === 'geojson') {
|
|
641
|
+
return props.geojson || props.overlays?.geojson || [];
|
|
642
|
+
}
|
|
643
|
+
if (!target || target === 'all' || target === 'active') {
|
|
644
|
+
return {
|
|
645
|
+
markers: props.markers || props.overlays?.markers,
|
|
646
|
+
polylines: props.polylines || props.overlays?.polylines,
|
|
647
|
+
polygons: props.polygons || props.overlays?.polygons,
|
|
648
|
+
circles: props.circles || props.overlays?.circles,
|
|
649
|
+
geojson: props.geojson || props.overlays?.geojson,
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
return target;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function fitBounds(
|
|
656
|
+
bounds?: LatLngBoundsExpression | LatLngTuple[] | MapBounds | 'markers' | 'polylines' | 'polygons' | 'all' | 'points' | 'lines',
|
|
657
|
+
options?: { padding?: [number, number]; maxZoom?: number; animate?: boolean; duration?: number }
|
|
658
|
+
) {
|
|
659
|
+
const resolved = resolveTargetBounds(bounds);
|
|
660
|
+
// #ifndef APP-PLUS
|
|
661
|
+
if (engine && typeof (engine as any).fitBounds === 'function') {
|
|
662
|
+
(engine as any).fitBounds(resolved, options);
|
|
663
|
+
}
|
|
664
|
+
// #endif
|
|
665
|
+
|
|
666
|
+
// #ifdef APP-PLUS
|
|
667
|
+
fitBoundsAction.value = {
|
|
668
|
+
bounds: resolved,
|
|
669
|
+
options,
|
|
670
|
+
timestamp: Date.now(),
|
|
671
|
+
};
|
|
672
|
+
// #endif
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (instance && instance.proxy) {
|
|
676
|
+
const proxy = instance.proxy as any;
|
|
677
|
+
proxy.doFitBounds = fitBounds;
|
|
678
|
+
proxy.fitBounds = fitBounds;
|
|
679
|
+
proxy.onRender_MapMove = (val: any) => {
|
|
680
|
+
const center = val?.center || val;
|
|
681
|
+
const zoom = val?.zoom;
|
|
682
|
+
if (center) {
|
|
683
|
+
emit('update:center', center);
|
|
684
|
+
emit('move', { center, zoom });
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
proxy.onRender_MapMoveEnd = (val: any) => {
|
|
688
|
+
const center = val?.center || val;
|
|
689
|
+
const zoom = val?.zoom;
|
|
690
|
+
if (center) {
|
|
691
|
+
emit('update:center', center);
|
|
692
|
+
emit('moveend', { center, zoom });
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
proxy.onRender_MapZoom = (z: any) => {
|
|
696
|
+
emit('update:zoom', z);
|
|
697
|
+
emit('zoom', z);
|
|
698
|
+
};
|
|
699
|
+
proxy.onRender_MapZoomEnd = (z: any) => {
|
|
700
|
+
emit('update:zoom', z);
|
|
701
|
+
emit('zoomend', z);
|
|
702
|
+
};
|
|
703
|
+
proxy.onRender_MapClick = (val: any) => {
|
|
704
|
+
const latLng = val?.latLng || val;
|
|
705
|
+
const point = val?.point || { x: 0, y: 0 };
|
|
706
|
+
emit('click', { latLng, point });
|
|
707
|
+
};
|
|
708
|
+
proxy.onRender_OverlayClick = (val: any) => {
|
|
709
|
+
emit('overlay-click', val);
|
|
710
|
+
if (val && val.type === 'marker') emit('marker-click', val.data);
|
|
711
|
+
if (val && val.type === 'polyline') emit('polyline-click', val.data);
|
|
712
|
+
if (val && val.type === 'polygon') emit('polygon-click', val.data);
|
|
713
|
+
if (val && val.type === 'circle') emit('circle-click', val.data);
|
|
714
|
+
};
|
|
715
|
+
proxy.onRender_ClusterClick = (val: any) => {
|
|
716
|
+
emit('cluster-click', val);
|
|
717
|
+
};
|
|
718
|
+
proxy.onRender_Ready = () => {
|
|
719
|
+
emit('ready', proxy);
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
|
|
547
723
|
// Unified Exposed methods
|
|
548
724
|
defineExpose({
|
|
549
725
|
setCenter(center: LatLngTuple, animate = true) {
|
|
@@ -561,6 +737,12 @@ defineExpose({
|
|
|
561
737
|
panTo(center: LatLngTuple, duration = 300) {
|
|
562
738
|
engine?.panTo(center, duration);
|
|
563
739
|
},
|
|
740
|
+
fitBounds(
|
|
741
|
+
bounds: LatLngBoundsExpression | LatLngTuple[] | MapBounds,
|
|
742
|
+
options?: { padding?: [number, number]; maxZoom?: number; animate?: boolean; duration?: number }
|
|
743
|
+
) {
|
|
744
|
+
fitBounds(bounds, options);
|
|
745
|
+
},
|
|
564
746
|
setTileUrl(url: string, subdomains?: string[]) {
|
|
565
747
|
engine?.setTileUrl(url, subdomains);
|
|
566
748
|
},
|
|
@@ -582,9 +764,20 @@ defineExpose({
|
|
|
582
764
|
setCircles(circles: CircleOptions[]) {
|
|
583
765
|
engine?.setCircles(circles);
|
|
584
766
|
},
|
|
767
|
+
setGeoJSON(data: any, style?: GeoJsonStyle) {
|
|
768
|
+
geojsonRevision.value++;
|
|
769
|
+
if (engine && typeof (engine as any).setGeoJSON === 'function') {
|
|
770
|
+
(engine as any).setGeoJSON(data, style);
|
|
771
|
+
}
|
|
772
|
+
},
|
|
585
773
|
clearOverlays() {
|
|
586
774
|
engine?.clearOverlays();
|
|
587
775
|
},
|
|
776
|
+
setClusterOptions(options: ClusterOptions) {
|
|
777
|
+
if (engine && typeof (engine as any).setClusterOptions === 'function') {
|
|
778
|
+
(engine as any).setClusterOptions(options);
|
|
779
|
+
}
|
|
780
|
+
},
|
|
588
781
|
resize(width?: number, height?: number) {
|
|
589
782
|
engine?.resize(width, height);
|
|
590
783
|
},
|
|
@@ -745,8 +938,183 @@ defineExpose({
|
|
|
745
938
|
.uni-custom-html-icon,
|
|
746
939
|
.uni-custom-img-icon,
|
|
747
940
|
.uni-custom-icon,
|
|
748
|
-
.uni-default-pin
|
|
941
|
+
.uni-default-pin,
|
|
942
|
+
.uni-cluster-marker-icon,
|
|
943
|
+
.uni-avatar-marker-icon {
|
|
749
944
|
background: transparent !important;
|
|
750
945
|
border: none !important;
|
|
751
946
|
}
|
|
947
|
+
|
|
948
|
+
.uni-cluster-bubble {
|
|
949
|
+
position: relative !important;
|
|
950
|
+
width: 44px !important;
|
|
951
|
+
height: 44px !important;
|
|
952
|
+
border-radius: 50% !important;
|
|
953
|
+
background: #ffffff !important;
|
|
954
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22), 0 0 0 3px #3b82f6 !important;
|
|
955
|
+
display: flex !important;
|
|
956
|
+
align-items: center !important;
|
|
957
|
+
justify-content: center !important;
|
|
958
|
+
cursor: pointer !important;
|
|
959
|
+
user-select: none !important;
|
|
960
|
+
box-sizing: border-box !important;
|
|
961
|
+
transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.uni-cluster-bubble:hover {
|
|
965
|
+
transform: scale(1.1) !important;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.uni-cluster-bubble .uni-cluster-icon {
|
|
969
|
+
width: 26px !important;
|
|
970
|
+
height: 26px !important;
|
|
971
|
+
display: flex !important;
|
|
972
|
+
align-items: center !important;
|
|
973
|
+
justify-content: center !important;
|
|
974
|
+
border-radius: 50% !important;
|
|
975
|
+
overflow: hidden !important;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.uni-cluster-bubble .uni-cluster-badge {
|
|
979
|
+
position: absolute !important;
|
|
980
|
+
top: -6px !important;
|
|
981
|
+
right: -8px !important;
|
|
982
|
+
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important;
|
|
983
|
+
color: #ffffff !important;
|
|
984
|
+
font-size: 11px !important;
|
|
985
|
+
font-weight: 700 !important;
|
|
986
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
987
|
+
height: 18px !important;
|
|
988
|
+
min-width: 18px !important;
|
|
989
|
+
padding: 0 5px !important;
|
|
990
|
+
border-radius: 10px !important;
|
|
991
|
+
display: flex !important;
|
|
992
|
+
align-items: center !important;
|
|
993
|
+
justify-content: center !important;
|
|
994
|
+
border: 2px solid #ffffff !important;
|
|
995
|
+
box-shadow: 0 2px 6px rgba(220, 38, 38, 0.45) !important;
|
|
996
|
+
box-sizing: border-box !important;
|
|
997
|
+
white-space: nowrap !important;
|
|
998
|
+
pointer-events: none !important;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/* Flowing polyline animation */
|
|
1002
|
+
@keyframes uni-polyline-flowing {
|
|
1003
|
+
from {
|
|
1004
|
+
stroke-dashoffset: 40px;
|
|
1005
|
+
}
|
|
1006
|
+
to {
|
|
1007
|
+
stroke-dashoffset: 0px;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.uni-flowing-polyline {
|
|
1012
|
+
animation: uni-polyline-flowing 1.5s linear infinite;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/* Avatar Bubble Marker Styles */
|
|
1016
|
+
.uni-avatar-marker-wrapper {
|
|
1017
|
+
position: relative !important;
|
|
1018
|
+
display: flex !important;
|
|
1019
|
+
flex-direction: column !important;
|
|
1020
|
+
align-items: center !important;
|
|
1021
|
+
justify-content: flex-start !important;
|
|
1022
|
+
cursor: pointer !important;
|
|
1023
|
+
user-select: none !important;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
.uni-avatar-bubble {
|
|
1027
|
+
position: relative !important;
|
|
1028
|
+
border-radius: 50% !important;
|
|
1029
|
+
background-color: #ffffff !important;
|
|
1030
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25) !important;
|
|
1031
|
+
display: flex !important;
|
|
1032
|
+
align-items: center !important;
|
|
1033
|
+
justify-content: center !important;
|
|
1034
|
+
box-sizing: border-box !important;
|
|
1035
|
+
overflow: visible !important;
|
|
1036
|
+
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.uni-avatar-marker-wrapper:hover .uni-avatar-bubble {
|
|
1040
|
+
transform: scale(1.12) !important;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
.uni-avatar-img {
|
|
1044
|
+
width: 100% !important;
|
|
1045
|
+
height: 100% !important;
|
|
1046
|
+
border-radius: 50% !important;
|
|
1047
|
+
object-fit: cover !important;
|
|
1048
|
+
display: block !important;
|
|
1049
|
+
pointer-events: none !important;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.uni-avatar-arrow {
|
|
1053
|
+
position: absolute !important;
|
|
1054
|
+
bottom: -6px !important;
|
|
1055
|
+
left: 50% !important;
|
|
1056
|
+
transform: translateX(-50%) !important;
|
|
1057
|
+
width: 0 !important;
|
|
1058
|
+
height: 0 !important;
|
|
1059
|
+
border-left: 5px solid transparent !important;
|
|
1060
|
+
border-right: 5px solid transparent !important;
|
|
1061
|
+
border-top-width: 6px !important;
|
|
1062
|
+
border-top-style: solid !important;
|
|
1063
|
+
z-index: 1 !important;
|
|
1064
|
+
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.2)) !important;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
.uni-avatar-badge {
|
|
1068
|
+
position: absolute !important;
|
|
1069
|
+
top: -2px !important;
|
|
1070
|
+
right: -2px !important;
|
|
1071
|
+
background: #ffffff !important;
|
|
1072
|
+
color: #1e293b !important;
|
|
1073
|
+
font-size: 8px !important;
|
|
1074
|
+
font-weight: 700 !important;
|
|
1075
|
+
line-height: 1 !important;
|
|
1076
|
+
height: 12px !important;
|
|
1077
|
+
min-width: 12px !important;
|
|
1078
|
+
padding: 0 2px !important;
|
|
1079
|
+
border-radius: 6px !important;
|
|
1080
|
+
display: flex !important;
|
|
1081
|
+
align-items: center !important;
|
|
1082
|
+
justify-content: center !important;
|
|
1083
|
+
border: 1px solid rgba(0, 0, 0, 0.08) !important;
|
|
1084
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25) !important;
|
|
1085
|
+
box-sizing: border-box !important;
|
|
1086
|
+
white-space: nowrap !important;
|
|
1087
|
+
z-index: 10 !important;
|
|
1088
|
+
pointer-events: none !important;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
@keyframes uni-avatar-pulse {
|
|
1092
|
+
0% {
|
|
1093
|
+
transform: scale(1);
|
|
1094
|
+
opacity: 0.85;
|
|
1095
|
+
}
|
|
1096
|
+
70% {
|
|
1097
|
+
transform: scale(1.6);
|
|
1098
|
+
opacity: 0;
|
|
1099
|
+
}
|
|
1100
|
+
100% {
|
|
1101
|
+
transform: scale(1.6);
|
|
1102
|
+
opacity: 0;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
.uni-avatar-pulse {
|
|
1107
|
+
position: absolute !important;
|
|
1108
|
+
top: 0 !important;
|
|
1109
|
+
left: 0 !important;
|
|
1110
|
+
width: 100% !important;
|
|
1111
|
+
height: 100% !important;
|
|
1112
|
+
border-radius: 50% !important;
|
|
1113
|
+
box-sizing: border-box !important;
|
|
1114
|
+
border-style: solid !important;
|
|
1115
|
+
border-width: 3px !important;
|
|
1116
|
+
animation: uni-avatar-pulse 1.8s cubic-bezier(0.24, 0, 0.38, 1) infinite !important;
|
|
1117
|
+
pointer-events: none !important;
|
|
1118
|
+
z-index: 0 !important;
|
|
1119
|
+
}
|
|
752
1120
|
</style>
|