Kamera i widok

Wybierz platformę: Android iOS JavaScript

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:

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.

Schemat właściwości kamery

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ą.

Zrzut ekranu mapy z kamerą ustawioną pod kątem 0 stopni przy powiększeniu 18.
Mapa wyświetlana z domyślnym kątem patrzenia kamery.
Diagram pokazujący domyślne położenie kamery bezpośrednio nad pozycją na mapie pod kątem 0 stopni.
Domyślny kąt patrzenia kamery.

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.

Zrzut ekranu mapy z kamerą pod kątem 45 stopni przy powiększeniu 18.
Mapa jest wyświetlana pod kątem 45 stopni.
Diagram przedstawiający kąt patrzenia kamery ustawiony na 45 stopni z poziomem powiększenia nadal ustawionym na 18.
Kąt widzenia kamery wynoszący 45 stopni.

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
Te obrazy pokazują wygląd różnych poziomów powiększenia:
Zrzut ekranu mapy w powiększeniu 5
Mapa w powiększeniu 5.
Zrzut ekranu mapy w powiększeniu 15
Mapa w powiększeniu 15.
Zrzut ekranu mapy przy powiększeniu 20
Mapa w powiększeniu 20.

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:

Diagram przedstawiający obwody położenia kamery, które są większe niż widoczny obszar.

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:

Diagram przedstawiający cel kamery umieszczony w prawym dolnym rogu obwodów położenia 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:

Diagram przedstawiający obwody szerokości geograficznej kamery, które są mniejsze od widocznego obszaru.

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));