diff --git a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx index 35c25310fb8..fff70ecda1a 100644 --- a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx @@ -22,7 +22,7 @@ import { MarkersLegend, MarkersLegendProps } from '../../components/MarkersLegen import { ObservablePropsWrapper } from '../../components/ObservablePropsWrapper'; import { StyleEditor } from '../../editor/StyleEditor'; import { getWebGLStyle, textMarker } from '../../style/markers'; -import { DEFAULT_SIZE, defaultStyleConfig, StyleConfig } from '../../style/types'; +import { DEFAULT_SIZE, defaultStyleConfig, StyleConfig, StyleConfigValues } from '../../style/types'; import { getDisplacement, getRGBValues, getStyleConfigState, styleUsesText } from '../../style/utils'; import { getStyleDimension } from '../../utils/utils'; @@ -122,12 +122,24 @@ export const markersLayer: MapLayerRegistryItem = { // Track if we find any line strings during feature processing let hasLineString = false; + // Track coordinates to avoid rendering duplicate markers at the same location + const processedMarkers = new Set(); + + // Helper function to create a robust uniqueness key + const createMarkerKey = (coordinates: number[], markerValues: StyleConfigValues): string => { + const coord = `${coordinates[0]},${coordinates[1]}`; + const { color, size, text, rotation } = markerValues; + return `markerAddressKey|${coord}|${color}|${size}|${text}|${rotation}`; + }; source.forEachFeature((feature) => { - const isLineString = feature.getGeometry()?.getType() === 'LineString'; + const geometry = feature.getGeometry(); + const isLineString = geometry?.getType() === 'LineString'; + if (isLineString) { hasLineString = true; } + const idx: number = feature.get('rowIndex'); const dims = style.dims; const values = { ...style.base }; @@ -144,6 +156,25 @@ export const markersLayer: MapLayerRegistryItem = { if (dims?.rotation) { values.rotation = dims.rotation.get(idx); } + + // For point geometries, check if we've already processed this marker + if (geometry?.getType() === 'Point') { + const coordinates = geometry.getCoordinates(); + + // Skip this feature if coordinates are invalid + if (!coordinates || coordinates.length < 2) { + return; + } + + const markerKey = createMarkerKey(coordinates, values); + + // Skip this feature if we've already processed a marker with identical properties + if (processedMarkers.has(markerKey)) { + return; + } + processedMarkers.add(markerKey); + } + if (!isLineString) { const colorString = tinycolor(theme.visualization.getColorByName(values.color)).toString(); const colorValues = getRGBValues(colorString);