Reputation: 33449
I'm facing the display of ghost markers in the top left corner of my leaflet map (with marker-cluster) assembled in svelte.
The markers disappear, when they are 'unclustered' through zooming.
I need to get rid of the ghost markers
This is a screencast of the behavior: https://screencast-o-matic.com/watch/c0VQIhVwYJb
It's even clearer what happens, if I simulate offline after load: https://somup.com/c0VQIOxVwu
The screencast is taken from a REPL I made for demonstration: https://svelte.dev/repl/0f6f706f236b4b6581861a5496e6a743?version=3.55.0
The relevant (IMHO) code is this:
<!-- App.svelte -->
<script> // define map, initialView and markers </script>
<Leaflet bind:map view={initialView}>
<MarkerCluster>
{#each markers as {lat, lng}, index}
<Marker latLng={[lat, lng]}>
<Pin>{index}</Pin>
</Marker>
{/each}
</MarkerCluster>
</Leaflet>
<!-- Leaflet.svelte -->
<script>
function createLeaflet(node) {
map = L.map(node, {
zoomControl: true,
gestureHandling: true,
}) ;
map.setView(view, zoom);
const tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
minZoom,
maxZoom,
useCache: true,
crossOrigin: true,
})
tileLayer.addTo(map);
return {
destroy() {
map.remove();
map = undefined;
},
};
}
</script>
<div style="height:{height};width:{width}" use:createLeaflet>
{#if map}
<slot {map} />
{/if}
</div>
<!-- MarkerCluster.svelte -->
<script>
const clusterGroup = L.markerClusterGroup({
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
spiderfyOnMaxZoom: true,
spiderfyDistanceMultiplier: 2,
});
const layer = getContext("layer");
setContext("layer", () => clusterGroup);
$: layer().addLayer(clusterGroup);
</script>
<slot />
<!-- Marker.svelte -->
<script>
function createMarker(
markerElement,
{ width, height, anchorX, anchorY, latLng }
) {
let icon = L.divIcon({
html: markerElement,
className: "map-marker",
iconSize: L.point(width, height),
iconAnchor: L.point(anchorX, anchorY),
});
marker = L.marker(latLng, { icon, title, alt, zIndexOffset, riseOnHover, riseOffset, opacity }).addTo(layer());
marker.data = {...data}
markers.push(marker)
return {
update({
width,
height,
anchorX,
anchorY,
latLng,
}) {
let icon = L.divIcon({
html: markerElement,
className: "map-marker",
iconSize: L.point(width, height),
iconAnchor: L.point(anchorX, anchorY),
});
marker.setIcon(icon);
},
destroy() {
if (marker) {
marker.remove();
marker = undefined;
}
},
};
}
</script>
<div use:createMarker>
{#if marker}
<slot />
{/if}
</div>
Upvotes: 0
Views: 193
Reputation: 19987
If you inspect the HTML elements from devtools. You'll see that when the markers are not ready to display, they're appended to the end of .leaflet-container
element.
When they're ready, they got moved into .leaflet-marker-icon
element, which you've customized to also have a classname .map-marker
.
With this knowledge, the problem can be easily fixed with some CSS.
Marker.svelte
<div
use:createMarker={{
width,
height,
anchorX,
anchorY,
latLng,
}}
class={(classNames ?? '') + ' marker-html-element'}
>
{#if marker}
<slot />
{/if}
</div>
<style>
:global(.map-marker .marker-html-element) {
display: block;
}
:global(.marker-html-element) {
display: none;
}
</style>
Upvotes: 0