From 0376e7106664640ca1a4c24d3ff9430d62001515 Mon Sep 17 00:00:00 2001 From: Pepe Ziberi Date: Sat, 21 Feb 2026 22:55:31 +0100 Subject: [PATCH] fix: symbols/text stay fixed on compass rotation, polygon area display in label box --- src/components/map/map-view.tsx | 37 ++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/components/map/map-view.tsx b/src/components/map/map-view.tsx index d1988bc..f6fd80a 100644 --- a/src/components/map/map-view.tsx +++ b/src/components/map/map-view.tsx @@ -23,6 +23,19 @@ function formatDistance(meters: number): string { return `${(meters / 1000).toFixed(2)} km` } +// Approximate polygon area in m² using the Shoelace formula on spherical coordinates +function polygonArea(ring: number[][]): number { + const toRad = Math.PI / 180 + const R = 6371000 + let area = 0 + const n = ring.length - 1 // exclude closing duplicate + for (let i = 0; i < n; i++) { + const j = (i + 1) % n + area += (ring[j][0] - ring[i][0]) * toRad * (2 + Math.sin(ring[i][1] * toRad) + Math.sin(ring[j][1] * toRad)) + } + return Math.abs(area * R * R / 2) +} + // Point-to-segment distance in screen pixels (for click detection on lines) function pointToSegmentDist(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number { const dx = x2 - x1, dy = y2 - y1 @@ -1396,7 +1409,7 @@ export function MapView({ pointer-events: none; ` - const marker = new maplibregl.Marker({ element: arrowEl, anchor: 'center' }) + const marker = new maplibregl.Marker({ element: arrowEl, anchor: 'center', rotationAlignment: 'viewport' }) .setLngLat(p2 as [number, number]) .addTo(map.current) markersRef.current.push(marker) @@ -1468,7 +1481,21 @@ export function MapView({ el.appendChild(labelLine) el.appendChild(infoLine) } else { - el.textContent = label + // Polygon: show label + area + const ring = (f.geometry.coordinates as number[][][])[0] + const area = polygonArea(ring) + const areaText = area < 10000 ? `${Math.round(area)} m²` : `${(area / 10000).toFixed(2)} ha` + + const labelLine = document.createElement('div') + labelLine.textContent = label + labelLine.style.cssText = 'font-size:11px;font-weight:600;line-height:1.2;' + + const infoLine = document.createElement('div') + infoLine.textContent = areaText + infoLine.style.cssText = 'font-size:8px;opacity:0.8;line-height:1.2;font-weight:400;' + + el.appendChild(labelLine) + el.appendChild(infoLine) } // Double-click to edit label — only in select mode @@ -1481,7 +1508,7 @@ export function MapView({ }) } - const marker = new maplibregl.Marker({ element: el, anchor: 'center' }) + const marker = new maplibregl.Marker({ element: el, anchor: 'center', rotationAlignment: 'viewport' }) .setLngLat(midpoint) .addTo(map.current) markersRef.current.push(marker) @@ -1568,7 +1595,7 @@ export function MapView({ } try { - const marker = new maplibregl.Marker({ element: wrapper, draggable: canEdit, anchor: 'center' }) + const marker = new maplibregl.Marker({ element: wrapper, draggable: canEdit, anchor: 'center', rotationAlignment: 'viewport' }) .setLngLat(coords) .addTo(map.current) @@ -1634,7 +1661,7 @@ export function MapView({ el.textContent = (f.properties.text as string) || '' wrapper.appendChild(el) - const marker = new maplibregl.Marker({ element: wrapper, draggable: canEdit, anchor: 'center' }) + const marker = new maplibregl.Marker({ element: wrapper, draggable: canEdit, anchor: 'center', rotationAlignment: 'viewport' }) .setLngLat(coords) .addTo(map.current)