Drive map markers by data, not visibility
All checks were successful
Build Docker Image / build (push) Successful in 5m20s
All checks were successful
Build Docker Image / build (push) Successful in 5m20s
This commit is contained in:
@@ -50,7 +50,6 @@ const props = withDefaults(defineProps<{
|
|||||||
hoveredItem?: HoveredItem | null
|
hoveredItem?: HoveredItem | null
|
||||||
pointColor?: string
|
pointColor?: string
|
||||||
entityType?: 'offer' | 'hub' | 'supplier'
|
entityType?: 'offer' | 'hub' | 'supplier'
|
||||||
visibleTypes?: Array<'offer' | 'hub' | 'supplier'>
|
|
||||||
initialCenter?: [number, number]
|
initialCenter?: [number, number]
|
||||||
initialZoom?: number
|
initialZoom?: number
|
||||||
infoLoading?: boolean
|
infoLoading?: boolean
|
||||||
@@ -71,7 +70,6 @@ const props = withDefaults(defineProps<{
|
|||||||
items: () => [],
|
items: () => [],
|
||||||
clusteredPoints: () => [],
|
clusteredPoints: () => [],
|
||||||
clusteredPointsByType: undefined,
|
clusteredPointsByType: undefined,
|
||||||
visibleTypes: undefined,
|
|
||||||
relatedPoints: () => []
|
relatedPoints: () => []
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -300,10 +298,6 @@ const getServerClusterCountLayerId = (type: 'offer' | 'hub' | 'supplier') => `${
|
|||||||
const getServerPointLayerId = (type: 'offer' | 'hub' | 'supplier') => `${props.mapId}-server-${type}-points`
|
const getServerPointLayerId = (type: 'offer' | 'hub' | 'supplier') => `${props.mapId}-server-${type}-points`
|
||||||
const getServerPointLabelLayerId = (type: 'offer' | 'hub' | 'supplier') => `${props.mapId}-server-${type}-point-labels`
|
const getServerPointLabelLayerId = (type: 'offer' | 'hub' | 'supplier') => `${props.mapId}-server-${type}-point-labels`
|
||||||
|
|
||||||
const isTypeVisible = (type: 'offer' | 'hub' | 'supplier') => {
|
|
||||||
if (!props.visibleTypes || props.visibleTypes.length === 0) return true
|
|
||||||
return props.visibleTypes.includes(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
const emitBoundsChange = (map: MapboxMapType) => {
|
const emitBoundsChange = (map: MapboxMapType) => {
|
||||||
const bounds = map.getBounds()
|
const bounds = map.getBounds()
|
||||||
@@ -757,9 +751,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
|
|||||||
'circle-stroke-width': 2,
|
'circle-stroke-width': 2,
|
||||||
'circle-stroke-color': '#ffffff'
|
'circle-stroke-color': '#ffffff'
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {}
|
||||||
visibility: isTypeVisible(type) ? 'visible' : 'none'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
map.addLayer({
|
map.addLayer({
|
||||||
@@ -769,8 +761,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
|
|||||||
filter: ['>', ['get', 'count'], 1],
|
filter: ['>', ['get', 'count'], 1],
|
||||||
layout: {
|
layout: {
|
||||||
'text-field': ['get', 'count'],
|
'text-field': ['get', 'count'],
|
||||||
'text-size': 14,
|
'text-size': 14
|
||||||
visibility: isTypeVisible(type) ? 'visible' : 'none'
|
|
||||||
},
|
},
|
||||||
paint: { 'text-color': '#ffffff' }
|
paint: { 'text-color': '#ffffff' }
|
||||||
})
|
})
|
||||||
@@ -783,8 +774,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
|
|||||||
layout: {
|
layout: {
|
||||||
'icon-image': `entity-icon-${type}`,
|
'icon-image': `entity-icon-${type}`,
|
||||||
'icon-size': 1,
|
'icon-size': 1,
|
||||||
'icon-allow-overlap': true,
|
'icon-allow-overlap': true
|
||||||
visibility: isTypeVisible(type) ? 'visible' : 'none'
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -797,8 +787,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
|
|||||||
'text-field': ['get', 'name'],
|
'text-field': ['get', 'name'],
|
||||||
'text-offset': [0, 1.8],
|
'text-offset': [0, 1.8],
|
||||||
'text-size': 12,
|
'text-size': 12,
|
||||||
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
|
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold']
|
||||||
visibility: isTypeVisible(type) ? 'visible' : 'none'
|
|
||||||
},
|
},
|
||||||
paint: {
|
paint: {
|
||||||
'text-color': '#ffffff',
|
'text-color': '#ffffff',
|
||||||
@@ -962,24 +951,7 @@ watch(() => props.relatedPoints, () => {
|
|||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
watch(() => props.visibleTypes, () => {
|
// no visibility toggling; layers are data-driven by query
|
||||||
if (!mapRef.value || !mapInitialized.value) return
|
|
||||||
if (!usesTypedClusters.value) return
|
|
||||||
for (const type of CLUSTER_TYPES) {
|
|
||||||
const visibility = isTypeVisible(type) ? 'visible' : 'none'
|
|
||||||
const layers = [
|
|
||||||
getServerClusterLayerId(type),
|
|
||||||
getServerClusterCountLayerId(type),
|
|
||||||
getServerPointLayerId(type),
|
|
||||||
getServerPointLabelLayerId(type)
|
|
||||||
]
|
|
||||||
layers.forEach((layerId) => {
|
|
||||||
if (mapRef.value?.getLayer(layerId)) {
|
|
||||||
mapRef.value.setLayoutProperty(layerId, 'visibility', visibility)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, { deep: true })
|
|
||||||
|
|
||||||
// Fit bounds when info loading finishes (all related data loaded)
|
// Fit bounds when info loading finishes (all related data loaded)
|
||||||
watch(() => props.infoLoading, (loading, wasLoading) => {
|
watch(() => props.infoLoading, (loading, wasLoading) => {
|
||||||
@@ -1048,14 +1020,13 @@ watch(() => props.clusteredPoints, (points) => {
|
|||||||
}
|
}
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
watch([() => props.clusteredPointsByType, () => props.visibleTypes], () => {
|
watch(() => props.clusteredPointsByType, () => {
|
||||||
if (!usesTypedClusters.value) return
|
if (!usesTypedClusters.value) return
|
||||||
if (!mapRef.value || !mapInitialized.value) return
|
if (!mapRef.value || !mapInitialized.value) return
|
||||||
if (didFitBounds.value) return
|
if (didFitBounds.value) return
|
||||||
|
|
||||||
const bounds = new LngLatBounds()
|
const bounds = new LngLatBounds()
|
||||||
const visible = props.visibleTypes && props.visibleTypes.length > 0 ? props.visibleTypes : CLUSTER_TYPES
|
CLUSTER_TYPES.forEach(type => {
|
||||||
visible.forEach(type => {
|
|
||||||
const points = serverClusteredGeoJsonByType.value[type]?.features ?? []
|
const points = serverClusteredGeoJsonByType.value[type]?.features ?? []
|
||||||
points.forEach((p) => {
|
points.forEach((p) => {
|
||||||
const coords = (p.geometry as GeoJSON.Point).coordinates as [number, number]
|
const coords = (p.geometry as GeoJSON.Point).coordinates as [number, number]
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
:map-id="mapId"
|
:map-id="mapId"
|
||||||
:items="isInfoMode ? [] : (useServerClustering ? [] : itemsWithCoords)"
|
:items="isInfoMode ? [] : (useServerClustering ? [] : itemsWithCoords)"
|
||||||
:clustered-points="isInfoMode ? [] : (useServerClustering && !useTypedClusters ? clusteredNodes : [])"
|
:clustered-points="isInfoMode ? [] : (useServerClustering && !useTypedClusters ? clusteredNodes : [])"
|
||||||
:clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)"
|
:clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)"
|
||||||
:visible-types="useServerClustering && useTypedClusters ? visibleTypes : undefined"
|
|
||||||
:use-server-clustering="useServerClustering && !isInfoMode"
|
:use-server-clustering="useServerClustering && !isInfoMode"
|
||||||
:point-color="activePointColor"
|
:point-color="activePointColor"
|
||||||
:entity-type="activeEntityType"
|
:entity-type="activeEntityType"
|
||||||
@@ -310,8 +309,6 @@ const activeClusterType = computed<'offer' | 'hub' | 'supplier'>(() => {
|
|||||||
return 'offer'
|
return 'offer'
|
||||||
})
|
})
|
||||||
|
|
||||||
const visibleTypes = computed(() => [activeClusterType.value])
|
|
||||||
|
|
||||||
const clusterLoading = computed(() => {
|
const clusterLoading = computed(() => {
|
||||||
if (!useTypedClusters.value) return singleClusterLoading.value
|
if (!useTypedClusters.value) return singleClusterLoading.value
|
||||||
if (activeClusterType.value === 'hub') return hubClusters.loading.value
|
if (activeClusterType.value === 'hub') return hubClusters.loading.value
|
||||||
|
|||||||
Reference in New Issue
Block a user