Allow cluster viewing
This commit is contained in:
parent
d48b0f7a1d
commit
f49e122361
3 changed files with 71 additions and 24 deletions
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts" context="module">
|
||||
import { createContext } from '$lib/utils/context';
|
||||
|
||||
// @ts-ignore
|
||||
const { get: getContext, set: setClusterContext } = createContext<() => L.MarkerClusterGroup>();
|
||||
|
||||
export const getClusterContext = () => {
|
||||
|
@ -13,45 +14,66 @@
|
|||
import 'leaflet.markercluster';
|
||||
import { getMapContext } from './map.svelte';
|
||||
import { MapMarkerResponseDto, getFileUrl } from '@api';
|
||||
import { Marker, Icon } from 'leaflet';
|
||||
import { assetInteractionStore } from '$lib/stores/asset-interaction.store';
|
||||
import L from 'leaflet';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
class AssetMarker extends L.Marker {
|
||||
marker: MapMarkerResponseDto;
|
||||
|
||||
constructor(marker: MapMarkerResponseDto) {
|
||||
super([marker.lat, marker.lon], {
|
||||
icon: new L.Icon({
|
||||
iconUrl: getFileUrl(marker.id, true),
|
||||
iconRetinaUrl: getFileUrl(marker.id, true),
|
||||
iconSize: [60, 60],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41]
|
||||
}),
|
||||
});
|
||||
|
||||
this.marker = marker;
|
||||
}
|
||||
|
||||
getAssetId(): string {
|
||||
return this.marker.id;
|
||||
}
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher<{ view: { assets: string[] } }>();
|
||||
|
||||
export let markers: MapMarkerResponseDto[];
|
||||
|
||||
const map = getMapContext();
|
||||
// @ts-ignore
|
||||
let cluster: L.MarkerClusterGroup;
|
||||
|
||||
setClusterContext(() => cluster);
|
||||
|
||||
onMount(() => {
|
||||
// @ts-ignore
|
||||
cluster = new L.MarkerClusterGroup({
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: true,
|
||||
spiderfyOnMaxZoom: true,
|
||||
zoomToBoundsOnClick: false,
|
||||
spiderfyOnMaxZoom: false,
|
||||
maxClusterRadius: 30,
|
||||
spiderLegPolylineOptions: { opacity: 0 },
|
||||
spiderfyDistanceMultiplier: 3
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
cluster.on('clusterclick', (event) => {
|
||||
// @ts-ignore
|
||||
const ids = event.layer.getAllChildMarkers().map(marker => marker.getAssetId());
|
||||
dispatch('view', { assets: ids });
|
||||
});
|
||||
|
||||
for (let marker of markers) {
|
||||
|
||||
const icon = new Icon({
|
||||
iconUrl: getFileUrl(marker.id, true),
|
||||
iconRetinaUrl: getFileUrl(marker.id, true),
|
||||
iconSize: [60, 60],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41]
|
||||
});
|
||||
|
||||
const leafletMarker = new Marker([marker.lat, marker.lon], {
|
||||
icon,
|
||||
alt: ''
|
||||
});
|
||||
const leafletMarker = new AssetMarker(marker);
|
||||
|
||||
leafletMarker.on('click', () => {
|
||||
assetInteractionStore.setViewingAssetId(marker.id);
|
||||
dispatch('view', { assets: [marker.id] });
|
||||
});
|
||||
|
||||
cluster.addLayer(leafletMarker);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
const map = getMapContext();
|
||||
|
||||
onMount(() => {
|
||||
// @ts-ignore
|
||||
tileLayer = new L.tileLayer.colorFilter(urlTemplate, options).addTo(map);
|
||||
});
|
||||
|
||||
|
|
|
@ -7,18 +7,40 @@
|
|||
import {
|
||||
assetInteractionStore,
|
||||
isViewingAssetStoreState,
|
||||
viewingAssetStoreState
|
||||
viewingAssetStoreState,
|
||||
|
||||
} from '$lib/stores/asset-interaction.store';
|
||||
import { colorTheme } from '$lib/stores/preferences.store';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let initialMapCenter = [48, 11];
|
||||
let initialMapCenter: [number, number] = [48, 11];
|
||||
|
||||
if (data.mapMarkers.length) {
|
||||
let firstMarker = data.mapMarkers[0];
|
||||
initialMapCenter = [firstMarker.lat, firstMarker.lon];
|
||||
}
|
||||
|
||||
let viewingAssets: string[] = [];
|
||||
let viewingAssetCursor = 0;
|
||||
|
||||
function onViewAssets(assets: string[]) {
|
||||
assetInteractionStore.setViewingAssetId(assets[0]);
|
||||
viewingAssets = assets;
|
||||
viewingAssetCursor = 0;
|
||||
}
|
||||
|
||||
function navigateNext() {
|
||||
if (viewingAssetCursor < viewingAssets.length - 1) {
|
||||
assetInteractionStore.setViewingAssetId(viewingAssets[++viewingAssetCursor]);
|
||||
}
|
||||
}
|
||||
|
||||
function navigatePrevious() {
|
||||
if (viewingAssetCursor > 0) {
|
||||
assetInteractionStore.setViewingAssetId(viewingAssets[--viewingAssetCursor]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<UserPageLayout user={data.user} title={data.meta.title}>
|
||||
|
@ -48,7 +70,7 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
<AssetMarkerCluster markers={data.mapMarkers} />
|
||||
<AssetMarkerCluster markers={data.mapMarkers} on:view={event => onViewAssets(event.detail.assets)} />
|
||||
</Map>
|
||||
</div>
|
||||
|
||||
|
@ -58,7 +80,9 @@
|
|||
{#if $isViewingAssetStoreState}
|
||||
<AssetViewer
|
||||
asset={$viewingAssetStoreState}
|
||||
showNavigation={false}
|
||||
showNavigation={viewingAssets.length > 1}
|
||||
on:navigate-next={navigateNext}
|
||||
on:navigate-previous={navigatePrevious}
|
||||
on:close={() => {
|
||||
assetInteractionStore.setIsViewingAsset(false);
|
||||
}}
|
||||
|
|
Loading…
Add table
Reference in a new issue