Drive map markers by data, not visibility
All checks were successful
Build Docker Image / build (push) Successful in 5m20s

This commit is contained in:
Ruslan Bakiev
2026-02-06 11:23:56 +07:00
parent 4bdefc9ce9
commit 1e761ca2a8
2 changed files with 8 additions and 40 deletions

View File

@@ -50,7 +50,6 @@ const props = withDefaults(defineProps<{
hoveredItem?: HoveredItem | null
pointColor?: string
entityType?: 'offer' | 'hub' | 'supplier'
visibleTypes?: Array<'offer' | 'hub' | 'supplier'>
initialCenter?: [number, number]
initialZoom?: number
infoLoading?: boolean
@@ -71,7 +70,6 @@ const props = withDefaults(defineProps<{
items: () => [],
clusteredPoints: () => [],
clusteredPointsByType: undefined,
visibleTypes: undefined,
relatedPoints: () => []
})
@@ -300,10 +298,6 @@ const getServerClusterCountLayerId = (type: 'offer' | 'hub' | 'supplier') => `${
const getServerPointLayerId = (type: 'offer' | 'hub' | 'supplier') => `${props.mapId}-server-${type}-points`
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 bounds = map.getBounds()
@@ -757,9 +751,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
},
layout: {
visibility: isTypeVisible(type) ? 'visible' : 'none'
}
layout: {}
})
map.addLayer({
@@ -769,8 +761,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
filter: ['>', ['get', 'count'], 1],
layout: {
'text-field': ['get', 'count'],
'text-size': 14,
visibility: isTypeVisible(type) ? 'visible' : 'none'
'text-size': 14
},
paint: { 'text-color': '#ffffff' }
})
@@ -783,8 +774,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
layout: {
'icon-image': `entity-icon-${type}`,
'icon-size': 1,
'icon-allow-overlap': true,
visibility: isTypeVisible(type) ? 'visible' : 'none'
'icon-allow-overlap': true
}
})
@@ -797,8 +787,7 @@ const initServerClusteringLayersByType = async (map: MapboxMapType) => {
'text-field': ['get', 'name'],
'text-offset': [0, 1.8],
'text-size': 12,
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
visibility: isTypeVisible(type) ? 'visible' : 'none'
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold']
},
paint: {
'text-color': '#ffffff',
@@ -962,24 +951,7 @@ watch(() => props.relatedPoints, () => {
}
}, { deep: true })
watch(() => props.visibleTypes, () => {
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 })
// no visibility toggling; layers are data-driven by query
// Fit bounds when info loading finishes (all related data loaded)
watch(() => props.infoLoading, (loading, wasLoading) => {
@@ -1048,14 +1020,13 @@ watch(() => props.clusteredPoints, (points) => {
}
}, { immediate: true })
watch([() => props.clusteredPointsByType, () => props.visibleTypes], () => {
watch(() => props.clusteredPointsByType, () => {
if (!usesTypedClusters.value) return
if (!mapRef.value || !mapInitialized.value) return
if (didFitBounds.value) return
const bounds = new LngLatBounds()
const visible = props.visibleTypes && props.visibleTypes.length > 0 ? props.visibleTypes : CLUSTER_TYPES
visible.forEach(type => {
CLUSTER_TYPES.forEach(type => {
const points = serverClusteredGeoJsonByType.value[type]?.features ?? []
points.forEach((p) => {
const coords = (p.geometry as GeoJSON.Point).coordinates as [number, number]

View File

@@ -18,8 +18,7 @@
:map-id="mapId"
:items="isInfoMode ? [] : (useServerClustering ? [] : itemsWithCoords)"
:clustered-points="isInfoMode ? [] : (useServerClustering && !useTypedClusters ? clusteredNodes : [])"
:clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)"
:visible-types="useServerClustering && useTypedClusters ? visibleTypes : undefined"
:clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)"
:use-server-clustering="useServerClustering && !isInfoMode"
:point-color="activePointColor"
:entity-type="activeEntityType"
@@ -310,8 +309,6 @@ const activeClusterType = computed<'offer' | 'hub' | 'supplier'>(() => {
return 'offer'
})
const visibleTypes = computed(() => [activeClusterType.value])
const clusterLoading = computed(() => {
if (!useTypedClusters.value) return singleClusterLoading.value
if (activeClusterType.value === 'hub') return hubClusters.loading.value