Dokumentation / Kartenansicht / Kameraposition auslesen

Kameraposition auslesen

Im Controller von MapConductor gibt es keine getCameraPosition(). Das gilt für alle 3 Plattformen gleichermaßen. Da es sich um eine Methode handelt, die man bei der Arbeit mit der Karte als erstes sucht, schreibe ich hier auf, was man stattdessen verwendet und warum sie nicht bereitgestellt wird.

Kurz gesagt: Die Kamera ist etwas, das man nicht abholt, sondern das man empfängt. Die Karte-Site (SDK) kennt die Änderungen der Kamera, und wir müssen sie nur empfangen.

01 · 3 Wege

Nutzen Sie sie je nach Anwendungsfall. In allen Fällen kommt dasselbe MapCameraPosition an, und der sichtbare Bereich befindet sich in visibleRegion.

Aktuellen Wert möchten
mapViewState.cameraPosition — jederzeit lesbar. Der sichtbare Bereich ist cameraPosition.visibleRegion.bounds.
Änderungen verfolgen möchten
onCameraMove / onCameraMoveEnd — wird auch während der Bewegung ausgelöst. Wenn die UI folgen soll, nutzen Sie dies.
Erweiterungsmodul
Als Overlay-Controller registrieren und onCameraChanged empfangen. So vermeiden Sie Konflikte um den einzelnen Listener-Slot des Karten-Controllers.
Plattform
Aus Status lesen
val camera = mapViewState.cameraPosition
val bounds = camera.visibleRegion?.bounds

// Änderungen verfolgen
MapView(
    state = mapViewState,
    onCameraMoveEnd = { camera -> reload(camera.visibleRegion?.bounds) },
)

02 · Warum es keine Get-Methode gibt

MapConductor basiert auf allen 3 Plattformen auf deklarativen UIs (Compose / SwiftUI / React). Bei deklarativen UIs gibt es genau einen Ort, der den „aktuellen Zustand“ hält, und die UI spiegelt ihn nur wider. Da auch die Kamera ein Zustand ist, gehört sie in den state.

Wenn man dem Controller Getter-Methoden hinzufügt, hat derselbe Wert zwei Ursprungsorte. Einerseits state, andererseits direktes Lesen aus dem SDK. Beide sollten gleich sein, aber es vergrößert nur die Möglichkeit einer Abweichung. Tatsächlich war das auch so; vor dem Entfernen baute ich im selben Frame zweimal die Kamera auf – einmal für das SDK-Event, einmal war es die Neuerstellung bei jedem Neuzeichnen.

Ein Push-basierter Fluss
Kameraereignis vom Karten-SDK
        ↓  der Anbieter liest die Rohwerte des SDK, rechnet in den einheitlichen Zoom um, hängt visibleRegion an
   state.updateCameraPosition(camera)
        ↓
   ├─ mapViewState.cameraPosition                    (jederzeit lesbar)
   ├─ onCameraMove / onCameraMoveEnd                 (Callbacks der App)
   └─ onCameraChanged registrierter Overlays         (Erweiterungsmodule)
Diese Form ist bei android-sdk / ios-sdk / react-sdk gleich. Die beiden nativen SDKs hatten ursprünglich keine Getter-API im Controller, nur react-sdk hatte eine, deshalb haben wir sie am 2026-08-06 entfernt.

03 · Die Kosten von Pull

Wenn man nur über Design spricht, neigt man dazu zu sagen „Man könnte ja noch eins hinzufügen“, also stelle ich Messwerte hier. Die Kamera einmal aufzubauen ist nicht billig.

Was bei einem einzigen Aufruf passiert

center / zoom / bearing / tilt aus dem SDK lesen → mit dem anbieter­spezifischen ZoomAltitudeConverter in ein einheitliches Zoom konvertieren → die vier Bildschirmecken rückprojizieren und visibleRegion zusammenbauen. Der letzte Schritt ist der aufwendigste und kein einfacher Getter.

Messwerte. Ich habe die MapLibre-Markerseite in Chromium geöffnet und gezählt, wie oft getCameraPosition() bei einem Drag (ca. 20 Frames panning) aufgerufen wurde.

Erstes Laden
Ein Drag
Als es Getter-Methoden gab
5
86
Nach dem Entfernen
3
30

Es nahm um ca. 65 % ab. Die Abnahme ist alles Neuerstellung. Obwohl ich einmal im SDK-Event aufbaute und in den state überführte, baute die View bei jedem Neuzeichnen ein weiteres Mal denselben Wert auf. Der Aufrufer war in allen 13 Views vorhanden, das heißt, sie alle warfen den Wert weg, den sie gerade erst per push gesendet hatten.

Im Stillstand ist es übrigens 0 Mal. Es lief nicht außer Kontrolle, es war eine Kostenart, die während der Bedienung sicher zu tragen kommt. Da sie im schwersten Moment der Karte oben draufpackt, merkt man es leicht.

Implementierung im Video · Android + MapLibreKotlin · Jetpack Compose
var camera by remember { mutableStateOf<MapCameraPosition?>(null) }

MapLibreMapView(
    state = mapViewState,
    modifier = Modifier.weight(1f),
    // Fires throughout the gesture — keep this handler cheap
    onCameraMove = { position -> camera = position },
    // Once, when the map settles. Fetching and redrawing belong here
    onCameraMoveEnd = { position -> viewModel.onCameraSettled(position) },
)

camera?.let { position ->
    Text("lat  %.5f".format(position.position.latitude))
    Text("lng  %.5f".format(position.position.longitude))
    Text("zoom %.2f".format(position.zoom))
    // Read the visible region off the value you were handed; do not rebuild it
    position.visibleRegion?.bounds?.let { bounds ->
        Text("SW ${bounds.southWest}  NE ${bounds.northEast}")
    }
}
Beispielvideo · Werte lesen während der Kartenbewegung
Video noch nicht aufgenommenWährend des Drags werden Breitengrad/Längengrad und Zoom, die per Callback empfangen wurden, auf dem Bildschirm ständig aktualisiert. Der Unterschied zwischen Pull und Push zeigt sich in dieser Art der Nachführung.

04 · Eine Frame-Verzögerung

mapViewState.cameraPosition ist „der zuletzt gepushte Wert“, also kann er rein logisch ein Frame älter sein als der aktuelle Wert des SDK. Das ist der einzige substanzielle Grund, einen Getter hinzuzufügen, also schreibe ich es ehrlich auf.

In der Praxis

onCameraMove wird auch während der Bewegung in jedem Frame ausgelöst, daher hält state immer mit dem vorherigen Frame Schritt. Weder bei der Darstellung, beim Datenabruf noch bei der Bereichsprüfung gibt es spürbare Unterschiede. Tatsächlich laufen alle 41 Browsertests weiterhin durch, nachdem die Abrufmethoden entfernt wurden.

Wenn es etwas bringt

Rendering, der vollständig mit den Frames beim Ziehen synchronisiert ist. Da das jedoch an der Renderingschleife des Karten‑SDK hängt, sollte dies nicht über die einheitliche API, sondern über den im Folgenden beschriebenen Ausweg gelöst werden.

05 · Wenn man trotzdem Rohwerte braucht

Wenn über statе nicht ausgereicht ist – etwa um sich mit der Zeichenschleife des Karten-SDK zu synchronisieren –, dann greifen Sie über MapViewHolder direkt auf die native Karteninstanz zu, ohne den Umweg über die einheitliche API zu nehmen. Das ist anbieterspezifischer Code, aber dafür am schnellsten und am genauesten.

Auf die native Ebene absteigen
const holder = mapViewState.getMapViewHolder();
const map = holder?.map as maplibregl.Map | undefined;
const liveZoom = map?.getZoom();
Im Inneren jedes Anbieters gibt es eine Logik, die die Rohwerte des SDK in ein einheitliches Zoom-Level umwandelt; die Werte für Kameraereignisse werden dort erzeugt. Das ist jedoch intern in der Implementierung und nicht Teil der öffentlichen Schnittstelle. Alle drei Plattformen verfolgen denselben Ansatz (android-sdk hat die private Methode getMapCameraPosition(), ios-sdk hat private currentCameraPosition(from:)).

Verwandte Seiten