@aiaiai-pt/design-system 0.27.0 → 0.28.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/components/MapCluster.svelte +21 -8
- package/package.json +1 -1
|
@@ -310,7 +310,14 @@
|
|
|
310
310
|
if (!data) return;
|
|
311
311
|
if (popup) {
|
|
312
312
|
selected = data;
|
|
313
|
-
if (coords)
|
|
313
|
+
if (coords) {
|
|
314
|
+
_popupOverlay?.setPosition(coords);
|
|
315
|
+
// Fly TO the clicked marker: animate the view so the marker (and its
|
|
316
|
+
// anchored popup) is centred — a clear "the map moved to what I
|
|
317
|
+
// tapped" gesture, not a subtle edge-nudge. The small ficha-resumo
|
|
318
|
+
// card opens above the now-centred marker and stays in view.
|
|
319
|
+
map?.getView().animate({ center: coords, duration: 400 });
|
|
320
|
+
}
|
|
314
321
|
} else {
|
|
315
322
|
onclick?.(data);
|
|
316
323
|
}
|
|
@@ -330,25 +337,31 @@
|
|
|
330
337
|
(/** @type {any} */ (feature.getGeometry()))?.getCoordinates(),
|
|
331
338
|
);
|
|
332
339
|
} else if (clustered?.length > 1) {
|
|
333
|
-
// A cluster
|
|
334
|
-
//
|
|
335
|
-
//
|
|
340
|
+
// A cluster ALWAYS expands first — zoom in toward it so the citizen
|
|
341
|
+
// picks an individual marker; only a SINGLE marker opens a popup.
|
|
342
|
+
// The lone exception is a genuinely STACKED pile (near-identical
|
|
343
|
+
// coords — stacked reports at one point are common in civic data)
|
|
344
|
+
// that can't split by zooming: once we're already at max zoom and
|
|
345
|
+
// it's still piled, fall back to opening the first item so it stays
|
|
346
|
+
// reachable instead of zoom-looping forever.
|
|
347
|
+
const view = map?.getView();
|
|
348
|
+
const currentZoom = view?.getZoom() ?? zoom;
|
|
349
|
+
const maxZoom = view?.getMaxZoom?.() ?? 19;
|
|
336
350
|
const coords = clustered.map((f) => f.getGeometry()?.getCoordinates()).filter(Boolean);
|
|
337
351
|
const lons = coords.map((c) => c[0]);
|
|
338
352
|
const lats = coords.map((c) => c[1]);
|
|
339
353
|
const spread = Math.max(...lons) - Math.min(...lons) + (Math.max(...lats) - Math.min(...lats));
|
|
340
|
-
|
|
354
|
+
const stacked = spread < 1; // metres in web-mercator units
|
|
355
|
+
if (stacked && currentZoom >= maxZoom - 0.5) {
|
|
341
356
|
selectMarker(
|
|
342
357
|
clustered[0].get('markerData'),
|
|
343
358
|
(/** @type {any} */ (feature.getGeometry()))?.getCoordinates(),
|
|
344
359
|
);
|
|
345
360
|
return;
|
|
346
361
|
}
|
|
347
|
-
const view = map?.getView();
|
|
348
|
-
const currentZoom = view?.getZoom() ?? zoom;
|
|
349
362
|
view?.animate({
|
|
350
363
|
center: feature.getGeometry()?.getCoordinates(),
|
|
351
|
-
zoom: currentZoom + 2,
|
|
364
|
+
zoom: Math.min(currentZoom + 2, maxZoom),
|
|
352
365
|
duration: 300,
|
|
353
366
|
});
|
|
354
367
|
}
|