Mapy w pakiecie Maps SDK na Androida można przechylać i obracać przy użyciu prostych gestów, dzięki czemu użytkownicy mogą dostosować mapę do najbardziej odpowiedniej dla nich orientacji. Na każdym poziomie powiększenia możesz przesuwać mapę lub zmieniać jej perspektywę przy niewielkich opóźnieniach, ponieważ są one mniejsze niż fragmenty mapy wektorowe.
Przykładowe fragmenty kodu
Repozytorium API Apigee na GitHubie zawiera przykład, który demonstruje działanie funkcji aparatu:
- CameraDemoActivity – Kotlin: zmiana pozycji kamery
- CameraDemoActivity (Java): zmiana pozycji kamery
Wstęp
Podobnie jak Mapy Google w internecie, pakiet Maps SDK na Androida reprezentuje powierzchnię świata (sferę) na ekranie urządzenia (płaską płaszczyznę) za pomocą rzutowania Mercator. W kierunku wschodnim i zachodnim mapa jest powtarzana w nieskończoność, tak jak świat płynnie się wokół siebie. W kierunku północnym i południowym mapa jest ograniczona do około 85 stopni na północ i 85 stopni na południe.
Uwaga: odwzorowanie Merkatora ma skończoną szerokość w długości, ale nieskończoną wysokość w obrębie szerokości geograficznej. „Odcinamy” zdjęcia mapy podstawowej za pomocą odwzorowania Merkatora pod kątem około +/-85 stopni, aby wynikowy kształt mapy był kwadratowy, co ułatwia logikę wyboru kafelków.
Maps SDK na Androida umożliwia zmianę punktu widzenia użytkownika na mapie przez modyfikowanie aparatu mapy.
Zmiany w aparacie nie spowodują żadnych zmian w znacznikach, nakładkach ani innych dodanych elementach graficznych, ale możesz samodzielnie zmienić to, co chcesz dodać, aby lepiej pasowały do nowego widoku.
Możesz nasłuchiwać gestów użytkowników na mapie, więc możesz zmieniać mapę w odpowiedzi na prośby użytkowników. Na przykład metoda wywołania zwrotnego OnMapClickListener.onMapClick()
odpowiada na jedno kliknięcie na mapie. Metoda otrzymuje szerokość i długość geograficzną lokalizacji kliknięcia, więc możesz zareagować, przesuwając lub powiększając widok do danego punktu.
Podobne metody są dostępne w przypadku klikania dymka znacznika lub
reagowania na gest przeciągania na znaczniku.
Możesz też nasłuchiwać ruchu kamery, aby aplikacja otrzymała powiadomienie, gdy kamera zacznie się poruszać, będzie w danym momencie lub przestaje się poruszać. Szczegółowe informacje znajdziesz w przewodniku po zdarzeniach zmiany kamery.
Położenie kamery
Widok mapy jest modelowany jako kamera patrząca w dół na płaskiej płaszczyźnie. Położenie kamery (a tym samym renderowanie mapy) jest określane przez te właściwości: cel (szerokość i długość geograficzna), kierowanie, pochylenie i powiększenie.
Cel (lokalizacja)
Cel kamery to lokalizacja pośrodku mapy określona jako współrzędne szerokości i długości geograficznej.
Szerokość geograficzna może wynosić od -85 do 85 stopni włącznie. Wartości powyżej lub poniżej tego zakresu będą ograniczane do najbliższej wartości z tego zakresu. Na przykład szerokość geograficzna równa 100 powoduje ustawienie wartości 85. Długość geograficzna mieści się w zakresie od -180 do 180 stopni włącznie. Wartości powyżej lub poniżej tego zakresu zostaną zapakowane w taki sposób, aby mieściły się w danym zakresie (-180, 180). Na przykład wartości 480, 840 i 1200 zostaną zapakowane w zakresie 120 stopni.Orientacja
Orientacja kamery określa kierunek kompasu, mierzony w stopniach od rzeczywistej północy, odpowiadający górnej krawędzi mapy. Jeśli narysujesz pionową linię od środka mapy do górnej krawędzi mapy, przesunięcie będzie odpowiadać kierunku kamery (mierzone w stopniach) względem rzeczywistej północy.
Orientacja 0 oznacza, że góra mapy wskazuje rzeczywistą północ. Wartość kierunku 90 oznacza, że góra mapy jest skierowana we wschód (90 stopni na kompasie). Wartość 180 oznacza górną część mapy leżącą w kierunku południowym.
Interfejs API Map Google umożliwia zmianę kierunku mapy. Na przykład osoba jadąca samochodem często obraca mapę drogową, aby dopasować ją do kierunku jazdy, a turyści korzystający z mapy i kompasu zwykle konfigurują mapę tak, aby linia pionowa wskazywała północ.
Pochylenie (kąt patrzenia)
Pochylenie określa położenie kamery na łuku bezpośrednio nad pozycją środkową mapy, mierzoną w stopniach od nadiru (kierunku wskazującego bezpośrednio pod kamerą). Wartość 0 oznacza, że kamera jest skierowana prosto w dół. Wartości większe niż 0 odpowiadają kamerze, która jest nachylona w kierunku horyzontu o określoną liczbę stopni. Po zmianie kąta patrzenia mapa wyświetla się w perspektywie, przy czym odległe obiekty wydają się mniejsze, a obiekty w pobliżu stają się większe. Oto ilustracje.
Na poniższych obrazach kąt patrzenia wynosi 0 stopni. Pierwszy obraz przedstawia schemat – pozycja 1 to pozycja kamery, a pozycja 2 – bieżąca pozycja na mapie. Powstała mapa jest widoczna pod nią.
Na poniższych obrazach kąt patrzenia wynosi 45 stopni. Zwróć uwagę, że kamera przesuwa się w połowie łuku między głową pionową (0 stopni) a podłożem (90 stopni) w pozycji 3. Kamera nadal jest skierowany na punkt środkowy mapy, ale obszar reprezentowany przez linię w pozycji 4 jest teraz widoczny.
Mapa na tym zrzucie ekranu jest nadal wyśrodkowana w tym samym punkcie co na oryginalnej mapie, ale na jej górze pojawiło się więcej obiektów. Gdy zwiększysz kąt powyżej 45 stopni, elementy pomiędzy aparatem a położeniem mapy stają się proporcjonalnie większe, a obiekty poza położeniem mapy stają się proporcjonalnie mniejsze, co daje efekt trójwymiarowy.
Zoom
Poziom powiększenia kamery określa skalę mapy. Przy większym powiększeniu na ekranie widać więcej szczegółów, a przy mniejszym stopniu widać na ekranie więcej szczegółów. Przy poziomie powiększenia 0 skala mapy jest taka, że cały świat ma szerokość około 256 dp (piksele niezależne od gęstości).
Zwiększenie poziomu powiększenia o 1 powoduje podwojenie szerokości ekranu. Dlatego przy powiększeniu N szerokość świata wynosi około 256 * 2N dp. Na przykład przy powiększeniu 2 cały świat ma około 1024 dp.
Poziom powiększenia nie musi być liczbą całkowitą. Zakres powiększenia dozwolony w przypadku mapy zależy od wielu czynników, w tym od celu, typu mapy i rozmiaru ekranu. Każda liczba spoza zakresu zostanie przekonwertowana na następną najbliższą prawidłową wartość, którą może być minimalny lub maksymalny poziom powiększenia. Poniższa lista pokazuje przybliżony poziom szczegółowości na poszczególnych poziomach powiększenia:
- 1: Świat
- 5: Ląd/kontynent
- 10: Miasto
- 15: Ulice
- 20. Budynki
Poruszanie aparatem
Interfejs API Map Google pozwala określić, która część świata jest widoczna na mapie. Służy do tego zmiana położenia kamery (a nie przesuwania mapy).
Po zmianie kamery możesz animować ruch kamery. Animacja interpoluje między atrybutami bieżącego aparatu i nowego. Możesz też kontrolować czas trwania animacji.
Aby zmienić położenie kamery, użyj przycisku CameraUpdate
, aby wskazać, w którym miejscu chcesz ją przesunąć. Interfejs API Map Google pozwala tworzyć wiele różnych typów CameraUpdate
za pomocą CameraUpdateFactory
. Dostępne są te ustawienia:
Zmiana poziomu powiększenia oraz ustawienie minimalnego/maksymalnego powiększenia
CameraUpdateFactory.zoomIn()
i CameraUpdateFactory.zoomOut()
obejmują element CameraUpdate
, który zmienia poziom powiększenia o 1,0, zachowując wszystkie pozostałe właściwości bez zmian.
CameraUpdateFactory.zoomTo(float)
daje CameraUpdate
, który zmienia poziom powiększenia na podaną wartość, zachowując wszystkie pozostałe właściwości bez zmian.
CameraUpdateFactory.zoomBy(float)
i CameraUpdateFactory.zoomBy(float, Point)
zapewniają CameraUpdate
, który zwiększa (lub zmniejsza, jeśli wartość jest ujemna) poziom powiększenia o podaną wartość. W tym drugim przypadku dany punkt jest ustawiany na ekranie w taki sposób, aby pozostał w tym samym miejscu (szerokość i długość geograficzna) oraz mógł zmieniać położenie kamery.
Warto ustawić preferowany minimalny lub maksymalny poziom powiększenia. Jest to przydatne na przykład wtedy, gdy chcesz kontrolować sposób, w jaki użytkownicy korzystają z aplikacji, gdy Twoja aplikacja wyświetla określony obszar wokół ciekawego miejsca lub używasz niestandardowej nakładki z kafelkami z ograniczonymi poziomami powiększenia.
Kotlin
private lateinit var map: GoogleMap map.setMinZoomPreference(6.0f) map.setMaxZoomPreference(14.0f)
Java
private GoogleMap map; map.setMinZoomPreference(6.0f); map.setMaxZoomPreference(14.0f);
Pamiętaj, że ze względów technicznych interfejs API może uniemożliwiać użytkownikom zbyt małe lub zbyt duże powiększenie. Na przykład widok satelitarny lub teren może mieć niższe maksymalne powiększenie niż podstawowe fragmenty mapy.
Zmiana pozycji kamery
Są 2 wygodne metody wprowadzania typowych zmian pozycji.
CameraUpdateFactory.newLatLng(LatLng)
udostępnia wartość CameraUpdate
, która zmienia szerokość i długość geograficzną kamery przy zachowaniu wszystkich pozostałych właściwości.
CameraUpdateFactory.newLatLngZoom(LatLng, float)
udostępnia przycisk CameraUpdate
, który zmienia szerokość, długość geograficzną i powiększenie kamery przy zachowaniu wszystkich pozostałych właściwości.
Aby uzyskać pełną elastyczność zmiany pozycji kamery, użyj funkcji CameraUpdateFactory.newCameraPosition(CameraPosition)
. Daje Ci to przycisk CameraUpdate
, który przenosi kamerę do określonej pozycji. CameraPosition
można uzyskać bezpośrednio, za pomocą new CameraPosition()
lub za pomocą CameraPosition.Builder
za pomocą new CameraPosition.Builder()
.
Przesuwanie (przewijanie)
CameraUpdateFactory.scrollBy(float, float)
udostępnia wartość CameraUpdate
, która zmienia szerokość i długość geograficzną kamery, by mapa przesuwała się o określoną liczbę pikseli. Dodatnia wartość x powoduje przesuwanie kamery w prawo, przez co mapa jest przesunięta w lewo. Dodatnia wartość y powoduje, że kamera przesuwa się w dół, przez co mapa wydaje się przesunięta do góry. Odwrotnie, ujemne wartości x powodują przesuwanie kamery w lewo, więc mapa jest przesunięta w prawo, a ujemne wartości y – w górę. Przewijanie zależy od bieżącej orientacji kamery. Jeśli na przykład pochylenie kamery wynosi 90 stopni, kierunek wschód jest ustawiony na „górę”.
Wyznaczanie granic
Wyznaczanie granic mapy
Czasami warto przesunąć kamerę tak, aby cały interesujący obszar był widoczny na największym możliwym poziomie powiększenia. Jeśli na przykład chcesz pokazać wszystkie stacje benzynowe znajdujące się w promieniu 5 km od bieżącego położenia użytkownika, możesz przesunąć kamerę tak, aby były one widoczne na ekranie. Aby to zrobić, oblicz wartość LatLngBounds
, która ma być widoczna na ekranie. Następnie za pomocą funkcji CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int
padding)
możesz uzyskać obiekt CameraUpdate
, który zmienia położenie kamery w taki sposób, że cały obiekt LatLngBounds
zmieści się na mapie, biorąc pod uwagę określone dopełnienie (w pikselach). Po zwróceniu wartości CameraUpdate
przerwa (w pikselach) między podanymi granicami a krawędzią mapy jest co najmniej równa określonemu dopełnieniu. Pamiętaj, że zarówno przechylenie, jak i wyświetlenie mapy będą wynosić 0.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngBounds(australiaBounds, 0));
Wyśrodkowanie mapy na obszarze
W niektórych przypadkach warto wyśrodkować kamerę w określonym obszarze, a nie w obrębie skrajnej krawędzi. Na przykład aby wyśrodkować kamerę
na kraju i utrzymać stałe powiększenie. W takim przypadku możesz skorzystać z podobnej metody, tworząc LatLngBounds
i używając CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom)
z LatLngBounds
.Metoda getCenter()
. Metoda getCenter() zwraca środek geograficzny: LatLngBounds
.
Kotlin
val australiaBounds = LatLngBounds( LatLng((-44.0), 113.0), // SW bounds LatLng((-10.0), 154.0) // NE bounds ) map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.center, 10f))
Java
LatLngBounds australiaBounds = new LatLngBounds( new LatLng(-44, 113), // SW bounds new LatLng(-10, 154) // NE bounds ); map.moveCamera(CameraUpdateFactory.newLatLngZoom(australiaBounds.getCenter(), 10));
Przeciążenie tej metody, newLatLngBounds(boundary, width, height,
padding)
, umożliwia określenie szerokości i wysokości prostokąta w pikselach, tak aby odpowiadały one wymiarom mapy. Prostokąt jest ustawiony tak, że jego środek jest taki sam jak widok mapy (jeśli określone wymiary są takie same jak w widoku mapy, to prostokąt zbiega się z widokiem mapy). Zwrócony obiekt CameraUpdate
przesunie kamerę w taki sposób, że określony element LatLngBounds
zostanie wyśrodkowany na ekranie wewnątrz danego prostokąta przy największym możliwym poziomie powiększenia (uwzględniając wymagane dopełnienie).
Uwaga: używaj prostszej metody newLatLngBounds(boundary, padding)
do wygenerowania CameraUpdate
tylko wtedy, gdy będzie ona używana do przesuwania kamery po zmianie układu mapy. Podczas układu interfejs API oblicza granice wyświetlania mapy, które są potrzebne do poprawnego rzutowania ramki ograniczającej. Dla porównania w przypadku mapy CameraUpdate
zwróconej przez bardziej skomplikowaną metodę newLatLngBounds(boundary, width, height, padding)
możesz użyć w dowolnym momencie, jeszcze zanim mapa zostanie zmieniona na układ, ponieważ interfejs API oblicza granice wyświetlania na podstawie przekazywanych argumentów.
Ograniczanie przesuwania w danym obszarze przez użytkownika
W powyższych scenariuszach ustalasz granice mapy, ale użytkownik może ją przewijać lub przesuwać poza te granice. Zamiast tego możesz ograniczyć granice szerokości i długości geograficznej punktu centralnego mapy (celu kamery), aby użytkownicy mogli tylko przewijać i przesuwać mapę tylko w tych granicach. Na przykład aplikacja handlowa w centrum handlowym lub na lotnisku może ograniczyć mapę do określonych granic, aby umożliwić użytkownikom przewijanie i przesuwanie w tych granicach.
Kotlin
// Create a LatLngBounds that includes the city of Adelaide in Australia. val adelaideBounds = LatLngBounds( LatLng(-35.0, 138.58), // SW bounds LatLng(-34.9, 138.61) // NE bounds ) // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds)
Java
// Create a LatLngBounds that includes the city of Adelaide in Australia. LatLngBounds adelaideBounds = new LatLngBounds( new LatLng(-35.0, 138.58), // SW bounds new LatLng(-34.9, 138.61) // NE bounds ); // Constrain the camera target to the Adelaide bounds. map.setLatLngBoundsForCameraTarget(adelaideBounds);
Na diagramie poniżej widać scenariusz, w którym cel kamery jest ograniczony do obszaru, który jest nieco większy od widocznego obszaru. Użytkownik może przewijać i przesuwać widok, pod warunkiem że cel kamery pozostaje w ograniczonym obszarze. Krzyżyk oznacza cel kamery:
Mapa zawsze wypełnia widoczny obszar, nawet jeśli spowoduje to wyświetlenie obszarów znajdujących się poza wyznaczonymi granicami. Jeśli na przykład ustawisz cel kamery w rogu ograniczonego obszaru, obszar poza rogiem będzie w widocznym obszarze widoczny, ale użytkownicy nie będą mogli przewijać go dalej. Ten scenariusz ilustruje poniższy diagram. Krzyżyk oznacza cel kamery:
Na poniższym schemacie cel kamery ma bardzo ograniczone granice, przez co użytkownik ma bardzo mało możliwości przewijania lub przesuwania mapy. Krzyżyk reprezentuje cel kamery:
Aktualizuję obraz z kamery
Aby zastosować ikonę CameraUpdate
do mapy, możesz natychmiast przesunąć kamerę lub płynnie ją animować. Aby błyskawicznie przesunąć kamerę za pomocą danego CameraUpdate
, wywołaj GoogleMap.moveCamera(CameraUpdate)
.
Możesz zwiększyć wygodę użytkowników, zwłaszcza w przypadku krótkich ruchów, animując zmianę. Aby to zrobić, zamiast dzwonić pod
GoogleMap.moveCamera
,
wywołaj GoogleMap.animateCamera
.
Nowe atrybuty mapy zostaną płynnie przeniesione. Najbardziej szczegółowa forma tej metody (GoogleMap.animateCamera(cameraUpdate, duration, callback)
) zawiera 3 argumenty:
cameraUpdate
CameraUpdate
opisujący, gdzie przesunąć kamerę.callback
- Obiekt, który implementuje
GoogleMap.CancellableCallback
. Ten uogólniony interfejs obsługi zadań definiuje 2 metody „onCancel()” i „onFinished()”. W przypadku animacji metody są wywoływane w tych sytuacjach:onFinish()
- Wywoływana, jeśli animacja zostanie odtworzona bez zakłóceń.
onCancel()
-
Wywoływana, gdy animacja zostanie przerwana przez wywołanie metody
stopAnimation()
lub rozpoczęcie nowego ruchu kamery.Ten problem może też wystąpić, gdy wywołasz metodę
GoogleMap.stopAnimation()
.
duration
- Oczekiwany czas trwania animacji w milisekundach w formie
int
.
Poniższe fragmenty kodu ilustrują typowe sposoby przesuwania kamery.
Kotlin
val sydney = LatLng(-33.88, 151.21) val mountainView = LatLng(37.4, -122.1) // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15f)) // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()) // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null) // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. val cameraPosition = CameraPosition.Builder() .target(mountainView) // Sets the center of the map to Mountain View .zoom(17f) // Sets the zoom .bearing(90f) // Sets the orientation of the camera to east .tilt(30f) // Sets the tilt of the camera to 30 degrees .build() // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
Java
LatLng sydney = new LatLng(-33.88,151.21); LatLng mountainView = new LatLng(37.4, -122.1); // Move the camera instantly to Sydney with a zoom of 15. map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 15)); // Zoom in, animating the camera. map.animateCamera(CameraUpdateFactory.zoomIn()); // Zoom out to zoom level 10, animating with a duration of 2 seconds. map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null); // Construct a CameraPosition focusing on Mountain View and animate the camera to that position. CameraPosition cameraPosition = new CameraPosition.Builder() .target(mountainView ) // Sets the center of the map to Mountain View .zoom(17) // Sets the zoom .bearing(90) // Sets the orientation of the camera to east .tilt(30) // Sets the tilt of the camera to 30 degrees .build(); // Creates a CameraPosition from the builder map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));