feat(krokier): Nordpfeil + Windrichtung + Export-Dokument (v1.6.0)
Macht aus dem digitalen Kroki ein echtes taktisches Lagebild: Karte: - Nordpfeil-Overlay (dreht mit dem Karten-Bearing mit) - Windrichtung in 8 Richtungen setzbar (Windrose mit Drift-Pfeil + Label "Wind aus NW"), pro Einsatz gespeichert (Project.windDirection) Export (PNG & PDF): - Nordpfeil, Massstabsbalken und Windanzeige werden in die Karte eingebrannt - PDF zusätzlich: Symbol-Legende (Namen aus /api/icons) + bestehende Kopfzeile (Einsatz/Ort/Zeit/Nr) → fertiges, weitergebbares Krokier-Dokument Technik: - windDirection: Schema + idempotente Migration + Zod-Validierung + Typ - Neue Komponente MapCompass (Nordpfeil/Windrose/Wind-Setzer) - MapView verfolgt Bearing über 'rotate'-Event Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import Moveable from 'react-moveable'
|
||||
import { getSymbolById, getSymbolDataUri } from '@/lib/fw-symbols'
|
||||
import type { Project, DrawFeature, DrawMode } from '@/types'
|
||||
import { MeasurePanel } from './measure-panel'
|
||||
import { MapCompass } from './map-compass'
|
||||
import { FALLBACK_HOSE_TYPES, type HoseTypeData, type MeasurementSummary } from '@/lib/hose-calc'
|
||||
|
||||
// Haversine distance between two [lng, lat] points in meters
|
||||
@@ -91,6 +92,9 @@ interface MapViewProps {
|
||||
/** Vollbild-Umschaltung (mobil als schwebender Button über der Karte) */
|
||||
isFullscreen?: boolean
|
||||
onToggleFullscreen?: () => void
|
||||
/** Windrichtung fürs Lagebild (Grad, „Wind aus") + Setter */
|
||||
windDirection?: number | null
|
||||
onWindChange?: (dir: number | null) => void
|
||||
}
|
||||
|
||||
export function MapView({
|
||||
@@ -110,6 +114,8 @@ export function MapView({
|
||||
onSymbolPlaced,
|
||||
isFullscreen,
|
||||
onToggleFullscreen,
|
||||
windDirection,
|
||||
onWindChange,
|
||||
}: MapViewProps) {
|
||||
const mapContainer = useRef<HTMLDivElement | null>(null)
|
||||
const map = useRef<maplibregl.Map | null>(null)
|
||||
@@ -120,6 +126,7 @@ export function MapView({
|
||||
const [isMapLoaded, setIsMapLoaded] = useState(false)
|
||||
const [activeBaseLayer, setActiveBaseLayer] = useState<'osm' | 'satellite' | 'swisstopo'>('osm')
|
||||
const [layerDropdownOpen, setLayerDropdownOpen] = useState(false)
|
||||
const [mapBearing, setMapBearing] = useState(0)
|
||||
const [measurePointCount, setMeasurePointCount] = useState(0)
|
||||
const [measureFinished, setMeasureFinished] = useState(false)
|
||||
// Messergebnis für das React-Panel (ersetzt das frühere innerHTML-DOM-Overlay)
|
||||
@@ -706,6 +713,9 @@ export function MapView({
|
||||
map.current.addControl(new maplibregl.NavigationControl(), 'bottom-right')
|
||||
map.current.addControl(new maplibregl.ScaleControl(), 'bottom-left')
|
||||
|
||||
// Bearing verfolgen, damit Nordpfeil/Windrose mit der Kartendrehung mitlaufen
|
||||
map.current.on('rotate', () => setMapBearing(map.current?.getBearing() || 0))
|
||||
|
||||
// Geolocation: eigene Position dauerhaft anzeigen (Punkt + Genauigkeit + Blickrichtung)
|
||||
const geolocate = new maplibregl.GeolocateControl({
|
||||
positionOptions: { enableHighAccuracy: true },
|
||||
@@ -2193,6 +2203,14 @@ export function MapView({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Nordpfeil + Windrose (Lagebild) */}
|
||||
<MapCompass
|
||||
bearing={mapBearing}
|
||||
windDirection={windDirection}
|
||||
canEdit={canEdit}
|
||||
onWindChange={(dir) => onWindChange?.(dir)}
|
||||
/>
|
||||
|
||||
{/* Moveable controls for selected symbol */}
|
||||
{isSymbolSelected && selectedSymbolRef.current && canEdit && (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user