Dokumentation / Kartenansicht / Kamera

Kamera — der schwierigste Teil der Abstraktion

Bei MapConductor ist die Vereinheitlichung der Kamera am schwierigsten und wertvollsten. Ein Kameramodell, das aus position, zoom, bearing, tilt und visibleRegion besteht, wird in mehr als 10 Karten-Engines mit derselben Bedeutung vereinheitlicht. Wenn Sie dieselbe MapCameraPosition übergeben, erhalten Sie bei jedem Anbieter dieselbe Ansicht.

POSITION
lat / lng
ZOOM
0 – 22
BEARING
0 – 360°
TILT
−60 – 60°

01 · Warum die Vereinheitlichung sinnvoll ist

Jede Karten-Engine verfügt über ein eigenes Kameramodell. Manche sprechen von Zoom, manche von Kamerahöhe, manche drehen sich um einen Bodenfokuspunkt, andere bewegen den Blickpunkt selbst. Wenn Sie das native SDK direkt verwenden, führt das Austauschen des Anbieters sofort zu „gleiche Zahl, aber andere Ansicht“, und Sie müssen sogar die Bildschirmlogik umschreiben.

MapConductor kapselt diesen Unterschied in einer Adapterebene und zeigt der App nur ein einziges Kameramodell. Dadurch wird die Kameraposition zu einem wert, das über Anbieter hinweg transportiert werden kann. Auf der Seite Camera Sync der Beispiel-App können Sie tatsächlich sehen, wie eine Kameraposition an alle Anbieter weitergegeben wird und dieselbe Stelle, derselbe Maßstab und dieselbe Neigung übereinstimmen.

DIFFERENCE 01

Zoom oder Höhe

2D-Kachel-Systeme drücken den Maßstab durch die Zoomstufe aus, 3D-Systeme durch Kamerahöhe oder Sichtweite. Auch die Einheiten und Bezugsgrößen sind unterschiedlich.

DIFFERENCE 02

Blickpunkt oder Blickrichtung

Ein Modell, das sich um einen Punkt auf der Erde dreht (Orbit), und ein Modell, das die Position und Ausrichtung der Kamera selbst beschreibt, existieren nebeneinander.

DIFFERENCE 03

Zulässiger Neigungsbereich

Der maximale Neigungswinkel und die Möglichkeit, nach oben zu neigen, unterscheiden sich je nach Engine. Keiner unterstützt eine negative Neigung.

Abbildung · wie ein moveCameraTo auf jeder Engine zur selben Ansicht wird
val camera = MapCameraPosition(
    position = geoPoint,
    zoom = 18.0,
    tilt = 70.0,
)
moveCameraTo(camera)
MapConductor
Einheitliches Kameramodell
position / zoom · bearing / tilt
Pro Anbieter
Karten-SDK-Adapter
Pro Anbieter
Karten-SDK-Adapter
Adapter übersetzen in die jeweilige native Kameradarstellung. Unterschiede zwischen zoom- und höhenbasiert oder fehlender Aufwärtsneigung werden hier aufgefangen.
Zoombasierte Engines (Google Maps · Mapbox · MapLibre …)
Höhenbasierte Engines (ArcGIS · Cesium · MapKit …)
Ein Eingang; unterwegs unterschiedliche native Ausdrücke — auf dem Bildschirm aber derselbe Ort, derselbe Maßstab, dieselbe Neigung.
Beispielvideo · Camera Sync (Synchronisierung einer Kameraposition mit allen Anbietern)

02 · Vereinheitlichtes Kameramodell

Die Kamera wird durch ein einziges MapCameraPosition dargestellt. Es gibt keinen anbieterspezifischen Typ; Sie erstellen nur diesen Wert und übergeben ihn an moveCameraTo.

Eigenschaften
Beschreibung
position
Die zentrale Bodenordinate, auf die die Kamera gerichtet ist.
zoom
Maßstab. Der Zoomlevel von Google Maps wird als Referenz für alle Anbieter normalisiert.
bearing
Azimuth (Drehwinkel von geographisch Nord).
tilt
Neigung. 0 ist senkrecht von oben, positiv ist eine geneigte Sicht nach vorne, negativ ist eine Blickrichtung über den Horizont nach oben.
paddings
Bereich, der durch die UI verdeckt ist. Berechnungen der Mitte und des Anpassens werden unter Abzug dieses Bereichs durchgeführt.
visibleRegion
Der tatsächliche Bodenbereich, der auf dem Bildschirm sichtbar ist. Enthält die Begrenzung (bounds) des Rechtecks und die Koordinaten der vier Ecken.

Mit copy() können nur Teile ausgetauscht werden; Vergleiche werden mit einer Toleranz von Zoom 0,01 und Neigung 0,01 durchgeführt. Dies verhindert, dass geringfügige Schwankungen der vom Anbieter zurückgegebenen Werte fälschlicherweise als „bewegt“ interpretiert werden.

Plattform

03 · Vereinheitlichung von Zoomlevel = Höhe

Der Zoom wird intern genauso behandelt wie die „Kamerahöhe“. Im `core` gibt es Konverter, die 2D-Tile-Zoom und 3D-Höhen/-Sichtweiten gegenseitig umwandeln können; die Werte aller Provider werden zunächst in einen gemeinsamen Zoom (Google-Maps-Standard) umgerechnet, bevor sie veröffentlicht werden.

Dieser Standard wurde nicht nur logisch festgelegt. Mit dem Kalibrierungstool der Beispiel-App wurde der tatsächlich sichtbare Bereich für jeden Motor gemessen, wenn derselbe Zoom angegeben wurde, und die Standardhöhe so kalibriert, dass die Flächen übereinstimmen. Deshalb ist Zoom 14 bei allen Providern gleich breit.

Abbildung · Zoomstufen und der Maßstab, den sie zeigen (ungefähr wie viele km quer über den Bildschirm passen)
0
≈ 40,000 km
Ganze Erde
Die ganze Welt in einer Ansicht — nur Umrisse der Kontinente.
3
≈ 5,000 km
Kontinent
Kontinente und Ozeane; Grenzen haben noch keine Bedeutung.
6
≈ 600 km
Land
Ein ganzes Land und wo seine Städte liegen.
10
≈ 40 km
Ballungsraum
Bebaute Flächen und Hauptstraßen — eine übliche Startansicht.
14
≈ 2.5 km
Stadtteil
Das Straßennetz ist lesbar; richtig für eine Liste von Filialpins.
17
≈ 300 m
Block
Kreuzungen und Gebäudegrundrisse — Fußgängernavigation.
20
≈ 40 m
Gebäude
Eingänge und punktgenaue Positionen.
Jede Stufe verdoppelt den Maßstab. Die Angaben gelten für den Äquator bei 256 px Bildschirmbreite; die tatsächliche Entfernung am Boden ändert sich mit dem Breitengrad.
LATITUDE

Derselbe Zoom braucht je nach Breitengrad eine andere Höhe

Web-Mercator vergrößert die Karte zu den Polen hin, deshalb unterscheidet sich die Kamerahöhe für eine Zoomstufe zwischen Äquator und hohen Breiten um ein Mehrfaches. Die Umrechnung Zoom ⇄ Höhe berücksichtigt das.

ZOOM 10 · nahe dem Äquator
≈ 5,200 m
ZOOM 10 · etwa 70° N
≈ 1,700 m
NATIVE
Native Werte auf diese Skala bringen
±0.0
Google Maps · Mapbox 2D — Als Referenz übernommen. Die einheitliche Zoomskala folgt dieser Familie.
+1.0
MapLibre · MapTiler · TomTom — Der native Zoom liegt eine Stufe tiefer, daher wird ein Versatz von +1,0 angewendet.
m
MapKit · ArcGIS · Cesium · Google 3D — Zwischen Zoom und Höhe bzw. Distanz umgerechnet, unter Berücksichtigung von Breitengrad und Neigung.
ZOOM RANGE
0.0 – 22.0
ZOOM FACTOR
2.0
ZOOM 0 ALTITUDE
171,319,879 m
MAPLIBRE OFFSET
+1.0

Konstant sind nur die Beziehung „ein Schritt pro Verdopplung“ und die Höhe von Zoom 0 als Referenz. Auch die Tatsache, dass die Bodendistanz bei gleichem Zoom mit höherer Breite kleiner wird, ist in die Umrechnung einbezogen, sodass sich der Maßstab zwischen Tokio und Honolulu nicht verschiebt.

04 · Pseudo-Unterstützung für tilt < 0

tilt akzeptiert Werte von −60 bis 60 Grad. Positive Werte sind die gewohnte schiefe Aufsicht, negative Werte sind eine Blickrichtung nach oben über den Horizont. Kein Kartenmotor kann dies direkt ausdrücken; alle SDKs akzeptieren für pitch nur Werte ≥ 0.

MapConductor ersetzt dies daher so, dass Position und Ausrichtung der Kamera erhalten bleiben, dem Motor aber ein positiver Neigungswert übergeben wird. Für die App kann negativer tilt direkt verwendet werden, und die abgerufene Kameraposition wird ebenfalls als negativer tilt zurückgegeben.

tilt = 0

Ein Grundriss, betrachtet von direkt oben. Ein Rechteck auf der Erdoberfläche wird direkt zu einem Rechteck auf dem Bildschirm.

tilt > 0

Eine schräge Ansicht, nach vorne geneigt. Auf der Erdoberfläche entsteht ein Trapez, das vorne schmaler und hinten breiter ist.

tilt < 0

Eine Aufsicht über den Horizont. Eine Perspektive, die den Himmel einschließt, und die nativ nicht existiert.

Wie die Nachbildung funktioniert
01
Augenpunkt und Höhe der Kamera bleiben stehen; nur das Bodenziel wandert entlang des Bearings nach vorn, um einen Betrag, der sich aus Höhe und Neigungswinkel ergibt.
02
Der Engine wird dann abs(tilt) als Neigung nach unten übergeben. Da Auge und Blickrichtung übereinstimmen, entspricht das Bild der Sicht nach oben. Engines der MapLibre-Familie erhalten feste Korrekturfaktoren auf Versatz und Zoom, damit auch der Bildausschnitt passt.
03
Beim Zurücklesen der Kamera läuft dieselbe Rechnung rückwärts: Vorwärtsversatz und Zoomkorrektur werden aufgehoben, sodass der logische negative Tilt und der ursprüngliche Mittelpunkt zurückkommen. Hin und zurück bleibt stabil.
Unterstützung für negativen Tilt
Android · alle Anbieter
OK
iOS · alle Anbieter
OK
React · alle außer Google Maps 2D
OK
React · Google Maps 2D
N/A

Die einzige Ausnahme ist Google Maps 2D auf React — die Rasterkarte der JavaScript-API. Ihre Neigung hängt von Browser- und Kachelbedingungen ab, sodass Höhe und Ausrichtung, auf denen die Nachbildung beruht, nicht steuerbar sind. Google Maps 3D (Map3DElement) unterstützt negativen Tilt.

TiltMapPageViewModel.kt
// Den Regler von −60 bis 60 einfach durchreichen; ein negativer Wert ist derselbe Aufruf
currentPosition = currentPosition.copy(tilt = tilt)
mapViewState.value?.moveCameraTo(currentPosition)
Beispielvideo · Tilt (−60〜60 kontinuierlich bewegen)

05 · VisibleRegion ― der tatsächlich sichtbare Bereich

Wenn die Kamera geneigt wird, wird das Bildschirmrechteck am Boden zu einem Trapez. Ein Rechteck, das nur Südwest und Nordost umfasst (bounds), kann den Unterschied im Bereich zwischen Vorder- und Hintergrund nicht ausdrücken. VisibleRegion enthält zusätzlich zu dem Rechteck die Bodenkoordinaten der vier Bildecken, sodass auch mit geneigter Kamera „der tatsächlich abgebildete Bereich“ behandelt werden kann.

near ist die untere Bildschirmkante, also die der Kamera nähere Seite; far ist die obere Kante, die entferntere Seite. left / right beziehen sich auf den Bildschirm, daher ändert sich ihre Bedeutung nicht, wenn die Karte mit bearing gedreht wird. Dank dieser vier Punkte können auch bei geneigter Karte Datenabrufbereich und Hinweise auf Quellen korrekt bestimmt werden.

farLeft
farRight
nearLeft
nearRight
Bildschirmrechteck → Trapez am Boden
Die ferne Kante ist breiter, die nahe schmaler. Bounds ist der Kasten um dieses Trapez.
bounds
Der Südwest-/Nordost-Kasten um das Trapez, für grobe Prüfungen und bestehende APIs.
nearLeft / nearRight
Bodenkoordinaten der unteren Bildschirmecken — die nahe Seite.
farLeft / farRight
Bodenkoordinaten der oberen Bildschirmecken — die ferne Seite, die sich mit zunehmender Neigung weiter öffnet.
Wofür
Daten für den sichtbaren Bereich laden, fitBounds und das Umschalten der Kachel-Quellenangaben.
VisibleRegionViewModel.kt
mapViewState.cameraPosition.visibleRegion?.let { region ->
    val sw = region.bounds.southWest
    val ne = region.bounds.northEast
    // Die vier Ecken eines geneigten Bildschirms — als Trapez nutzbar
    val corners = listOf(region.nearLeft, region.nearRight, region.farLeft, region.farRight)
}

Verwandte Seiten