Kamera i widok

Wybierz platformę: Android iOS JavaScript

Mapy w pakiecie Maps SDK na Androida można przechylać i obracać za pomocą prostych gestów, dzięki czemu użytkownicy mogą dostosowywać orientację mapy do swoich potrzeb. Na dowolnym poziomie powiększenia możesz przesuwać mapę lub zmieniać jej perspektywę z bardzo małym opóźnieniem dzięki mniejszemu rozmiarowi kafelków mapy wektorowej.

Przykładowe fragmenty kodu

Repozytorium ApiDemos na GitHubie zawiera przykład, który pokazuje funkcje aparatu:

Wprowadzenie

Podobnie jak Mapy Google w internecie, pakiet SDK Map Google na Androida przedstawia powierzchnię Ziemi (sferę) na ekranie urządzenia (płaskiej powierzchni) za pomocą projekcji Merkatora. W kierunku wschód-zachód mapa powtarza się w nieskończoność, ponieważ świat płynnie się na niej zawija. W kierunku północnym i południowym mapa jest ograniczona do około 85 stopni szerokości geograficznej północnej i 85 stopni szerokości geograficznej południowej.

Uwaga: projekcja Mercatora ma skończoną szerokość wzdłużnie, ale nieskończoną wysokość w kierunku poprzecznym. Obrazy mapy bazowej „odcinamy” przy użyciu projekcji Mercatora przy około +/- 85 stopniach, aby uzyskać kwadratowy kształt mapy, co ułatwia wybieranie kafelków.

Pakiet Maps SDK na Androida umożliwia zmianę punktu widzenia użytkownika na mapę przez modyfikowanie kamery mapy.

Zmiany w kamerze nie wpłyną na dodane przez Ciebie znaczniki, nakładki ani inne elementy graficzne, ale możesz je zmienić, aby lepiej pasowały do nowego widoku.

Możesz nasłuchiwać gestów użytkownika na mapie i zmieniać ją w odpowiedzi na jego prośby. Na przykład metoda wywołania zwrotnego OnMapClickListener.onMapClick() reaguje na pojedyncze kliknięcie mapy. Metoda otrzymuje szerokość i długość geograficzną miejsca dotknięcia, więc możesz odpowiedzieć, przesuwając lub powiększając widok do tego punktu. Podobne metody są dostępne w przypadku reagowania na kliknięcia dymka markera lub na gest przeciągnięcia markera.

Możesz też nasłuchiwać ruchów kamery, aby aplikacja otrzymywała powiadomienia, gdy kamera zaczyna się poruszać, porusza się lub przestaje się poruszać. Więcej informacji znajdziesz w przewodniku po zdarzeniach zmiany kamery.

Pozycja kamery

Widok mapy jest modelowany jako kamera skierowana w dół na płaską powierzchnię. Położenie kamery (a tym samym renderowanie mapy) jest określone przez te właściwości: target (lokalizacja określona przez szerokość i długość geograficzną), bearing, tiltzoom.

Diagram właściwości kamery

Miejsce docelowe (lokalizacja)

Punkt docelowy kamery to lokalizacja środka mapy określona za pomocą współrzędnych geograficznych.

Szerokość geograficzna może się mieścić w zakresie od -85 do 85 stopni. Wartości powyżej lub poniżej tego zakresu zostaną zmienione na najbliższą wartość w tym zakresie. Na przykład podanie szerokości geograficznej 100 spowoduje 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ą przekształcone tak, aby mieściły się w zakresie (-180, 180). Na przykład wartości 480, 840 i 1200 zostaną zaokrąglone do 120 stopni.

Kierunek (orientacja)

Kierunek kamery określa kierunek kompasu mierzony w stopniach od północy geograficznej, który odpowiada górnej krawędzi mapy. Jeśli narysujesz pionową linię od środka mapy do jej górnej krawędzi, uzyskasz kierunek, w którym jest skierowany aparat (mierzony w stopniach) względem północy geograficznej.

Wartość 0 oznacza, że górna część mapy wskazuje północ geograficzną. Wartość 90 oznacza, że góra mapy jest skierowana na wschód (90 stopni na kompasie). Wartość 180 oznacza, że górna część mapy jest skierowana na południe.

Interfejs API Map Google umożliwia zmianę kierunku mapy. Na przykład kierowca samochodu często obraca mapę drogową, aby dopasować ją do kierunku jazdy, a turyści korzystający z mapy i kompasu zwykle orientują mapę tak, aby pionowa linia wskazywała północ.

Przechylenie (kąt widzenia)

Pochylenie określa położenie kamery na łuku bezpośrednio nad środkiem mapy, mierzone w stopniach od nadiru (kierunku skierowanego bezpośrednio pod kamerę). Wartość 0 odpowiada kamerze skierowanej prosto w dół. Wartości większe od 0 odpowiadają kamerze skierowanej w stronę horyzontu o określoną liczbę stopni. Gdy zmienisz kąt widzenia, mapa będzie wyświetlana w perspektywie, w której odległe obiekty są mniejsze, a pobliskie – większe. Ilustrują to poniższe przykłady.

Na obrazach poniżej kąt widzenia wynosi 0 stopni. Pierwszy obraz przedstawia schemat tej sytuacji. Pozycja 1 to pozycja kamery, a pozycja 2 to bieżąca pozycja na mapie. Wynikowa mapa jest widoczna poniżej.

Zrzut ekranu mapy z kamerą ustawioną pod kątem widzenia 0 stopni i poziomem powiększenia 18.
Mapa wyświetlana z domyślnym kątem widzenia kamery.
Diagram przedstawiający domyślną pozycję kamery bezpośrednio nad pozycją na mapie pod kątem 0 stopni.
Domyślny kąt widzenia kamery.

Na obrazach poniżej kąt widzenia wynosi 45 stopni. Zwróć uwagę, że kamera przesuwa się w połowie łuku między pozycją bezpośrednio nad głową (0 stopni) a ziemią (90 stopni), aby zająć pozycję 3. Kamera nadal jest skierowana na środek mapy, ale widoczny jest teraz obszar reprezentowany przez linię w pozycji 4.

Zrzut ekranu mapy z kamerą ustawioną pod kątem 45 stopni i powiększeniem 18.
Mapa wyświetlana pod kątem 45 stopni.
Diagram pokazujący kąt widzenia kamery ustawiony na 45 stopni, a poziom powiększenia nadal ustawiony 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 u góry pojawiło się więcej elementów. Gdy zwiększysz kąt powyżej 45 stopni, obiekty między kamerą a pozycją na mapie będą proporcjonalnie większe, a obiekty za pozycją na mapie będą proporcjonalnie mniejsze, co da 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 – większą część świata. Przy poziomie powiększenia 0 skala mapy jest taka, że cały świat ma szerokość około 256 dp (pikseli niezależnych od gęstości).

Zwiększenie poziomu powiększenia o 1 punkt powoduje podwojenie szerokości świata na ekranie. Dlatego na poziomie powiększenia N szerokość świata wynosi w przybliżeniu 256 * 2N dp. Na przykład przy poziomie powiększenia 2 cały świat ma szerokość około 1024 dp.

Poziom powiększenia nie musi być liczbą całkowitą. Zakres poziomów powiększenia dozwolonych na mapie zależy od wielu czynników, w tym od miejsca docelowego, typu mapy i rozmiaru ekranu. Każda liczba spoza zakresu zostanie przekonwertowana na najbliższą prawidłową wartość, która może być minimalnym lub maksymalnym poziomem 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
Obrazy poniżej pokazują, jak wyglądają różne poziomy powiększenia:
Zrzut ekranu mapy na poziomie powiększenia 5
Mapa na poziomie powiększenia 5.
Zrzut ekranu mapy na poziomie powiększenia 15
Mapa na poziomie powiększenia 15.
Zrzut ekranu mapy na poziomie powiększenia 20
Mapa na poziomie powiększenia 20.

Przesuwanie kamery

Interfejs API Map umożliwia zmianę części świata widocznej na mapie. Możesz to zrobić, zmieniając położenie kamery (w przeciwieństwie do przesuwania mapy).

Gdy zmienisz kamerę, możesz animować wynikowy ruch kamery. Animacja interpoluje między bieżącymi atrybutami kamery a nowymi atrybutami kamery. Możesz też kontrolować czas trwania animacji.

Aby zmienić pozycję kamery, musisz określić, gdzie chcesz ją przenieść, używając CameraUpdate. Interfejs API Map Google umożliwia tworzenie wielu różnych typów CameraUpdate za pomocą CameraUpdateFactory. Dostępne są te ustawienia:

Zmiana poziomu powiększenia i ustawianie minimalnego/maksymalnego powiększenia

CameraUpdateFactory.zoomIn()CameraUpdateFactory.zoomOut() dają CameraUpdate, który zmienia poziom powiększenia o 1,0, zachowując wszystkie inne właściwości bez zmian.

CameraUpdateFactory.zoomTo(float) zapewnia CameraUpdate, który zmienia poziom powiększenia na podaną wartość, zachowując wszystkie inne właściwości bez zmian.

CameraUpdateFactory.zoomBy(float) i CameraUpdateFactory.zoomBy(float, Point) dają CameraUpdate, które zwiększa (lub zmniejsza, jeśli wartość jest ujemna) poziom powiększenia o podaną wartość. Ta druga opcja ustala dany punkt na ekranie tak, aby pozostawał w tym samym miejscu (szerokość i długość geograficzna), i może zmienić położenie kamery, aby to osiągnąć.

Może się okazać, że warto ustawić preferowany minimalny lub maksymalny poziom powiększenia. Może to być przydatne np. do kontrolowania działania aplikacji, jeśli wyświetla ona zdefiniowany obszar wokół punktu orientacyjnego lub jeśli używasz niestandardowej nakładki kafelkowej z ograniczonym zestawem poziomów 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 istnieją kwestie techniczne, które mogą uniemożliwić interfejsowi API zbyt duże lub zbyt małe powiększenie. Na przykład widok satelitarny lub terenowy może mieć mniejsze maksymalne powiększenie niż kafelki mapy bazowej.

Zmiana pozycji kamery

W przypadku typowych zmian pozycji dostępne są 2 wygodne metody. CameraUpdateFactory.newLatLng(LatLng) – podaje CameraUpdate, które zmienia szerokość i długość geograficzną kamery, zachowując wszystkie inne właściwości. CameraUpdateFactory.newLatLngZoom(LatLng, float) zapewnia CameraUpdate, które zmienia szerokość i długość geograficzną oraz powiększenie kamery, zachowując wszystkie inne właściwości.

Aby mieć pełną swobodę w zakresie zmiany pozycji kamery, użyj CameraUpdateFactory.newCameraPosition(CameraPosition) które daje CameraUpdate, które przesuwa kamerę do podanej pozycji. CameraPosition można uzyskać bezpośrednio, używając new CameraPosition(), lub za pomocą CameraPosition.Builder, używając new CameraPosition.Builder().

Przesuwanie (przewijanie)

CameraUpdateFactory.scrollBy(float, float) daje CameraUpdate, które zmienia szerokość i długość geograficzną kamery, tak aby mapa przesunęła się o określoną liczbę pikseli. Dodatnia wartość x powoduje przesunięcie kamery w prawo, dzięki czemu mapa wydaje się przesunięta w lewo. Dodatnia wartość y powoduje przesunięcie kamery w dół, dzięki czemu mapa wydaje się przesunięta w górę. Z kolei ujemne wartości x powodują przesunięcie kamery w lewo, tak aby mapa wydawała się przesunięta w prawo, a ujemne wartości y powodują przesunięcie kamery w górę. Przewijanie jest względne w stosunku do bieżącej orientacji kamery. Jeśli np. kamera jest skierowana na wschód (90 stopni), to wschód jest „górą”.

Wyznaczanie granic

Ustawianie granic mapy

Czasami warto przesunąć kamerę tak, aby cały interesujący nas obszar był widoczny przy największym możliwym powiększeniu. Jeśli na przykład wyświetlasz wszystkie stacje benzynowe w promieniu 8 km od bieżącej pozycji użytkownika, możesz przesunąć kamerę tak, aby wszystkie były widoczne na ekranie. Aby to zrobić, najpierw oblicz LatLngBounds, które chcesz wyświetlić na ekranie. Możesz wtedy użyć funkcji CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int padding), aby uzyskać CameraUpdate, która zmienia pozycję kamery tak, aby podany parametr LatLngBounds mieścił się w całości na mapie z uwzględnieniem określonego dopełnienia (w pikselach). Zwrócony parametr CameraUpdate zapewnia, że odstęp (w pikselach) między podanymi granicami a krawędzią mapy będzie co najmniej tak duży, jak określone dopełnienie. Pamiętaj, że nachylenie i kierunek 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środkowywanie mapy w obszarze

W niektórych przypadkach możesz chcieć wyśrodkować kamerę w określonych granicach zamiast uwzględniać skrajne krawędzie. Na przykład aby wyśrodkować widok kamery na kraj, zachowując stałe powiększenie. W takim przypadku możesz użyć podobnej metody, tworząc LatLngBounds i używając CameraUpdateFactory.newLatLngZoom(LatLng latLng, float zoom)LatLngBounds.getCenter(). Metoda getCenter() zwróci środek geograficzny obiektu 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 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 umieszczony tak, aby jego środek pokrywał się ze środkiem widoku mapy (jeśli podane wymiary są takie same jak wymiary widoku mapy, prostokąt pokrywa się z widokiem mapy). Zwrócony element CameraUpdate przesunie kamerę tak, aby określone elementy LatLngBounds były wyśrodkowane na ekranie w danym prostokącie przy największym możliwym poziomie powiększenia, z uwzględnieniem wymaganego dopełnienia.

Uwaga: używaj prostszej metodynewLatLngBounds(boundary, padding)do generowania CameraUpdate tylko wtedy, gdy ma ona służyć do przesuwania kamery po ułożeniu mapy. Podczas układu interfejs API oblicza granice wyświetlania mapy, które są potrzebne do prawidłowego rzutowania ramki ograniczającej. Dla porównania, wartość CameraUpdate zwróconą przez bardziej złożoną metodę newLatLngBounds(boundary, width, height, padding) możesz wykorzystać w dowolnym momencie, nawet zanim mapa zostanie ułożona, ponieważ interfejs API oblicza granice wyświetlania na podstawie przekazanych argumentów.

Ograniczanie przesuwania przez użytkownika do danego obszaru

W powyższych scenariuszach ustawiasz granice mapy, ale użytkownik może przewijać lub przesuwać mapę poza te granice. Zamiast tego możesz ograniczyć granice środka mapy (punktu docelowego kamery), aby użytkownicy mogli przewijać i przesuwać mapę tylko w tych granicach. Na przykład aplikacja handlowa dla centrum handlowego lub lotniska może ograniczyć mapę do określonych granic, umożliwiając 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);

      

Poniższy diagram ilustruje sytuację, w której cel kamery jest ograniczony do obszaru nieco większego niż widoczny obszar. Użytkownik może przewijać i przesuwać widok, o ile punkt docelowy kamery pozostaje w ograniczonym obszarze. Krzyżyk oznacza cel kamery:

Diagram przedstawiający obiekt LatLngBounds kamery, który jest większy niż widoczny obszar.

Mapa zawsze wypełnia widoczny obszar, nawet jeśli powoduje to wyświetlanie obszarów znajdujących się poza zdefiniowanymi granicami. Jeśli na przykład umieścisz cel kamery w rogu ograniczonego obszaru, obszar za rogiem będzie widoczny w obszarze wyświetlania, ale użytkownicy nie będą mogli przewinąć go dalej. Poniższy diagram ilustruje ten scenariusz. Krzyżyk oznacza cel kamery:

Diagram przedstawiający cel kamery umieszczony w prawym dolnym rogu obiektu LatLngBounds kamery.

Na poniższym diagramie cel kamery ma bardzo ograniczone granice, co daje użytkownikowi bardzo małą możliwość przewijania lub przesuwania mapy. Krzyżyk reprezentuje cel kamery:

Diagram przedstawiający obiekt LatLngBounds kamery, który jest mniejszy niż
      obszar widoczny.

Aktualizowanie widoku z kamery

Aby zastosować CameraUpdate do mapy, możesz natychmiast przesunąć kamerę lub płynnie ją animować. Aby natychmiast przesunąć kamerę o podaną wartość CameraUpdate, możesz wywołać funkcję 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ć, kliknij GoogleMap.moveCamera zadzwoń GoogleMap.animateCamera. Mapa płynnie przesunie się do nowych atrybutów. Najbardziej szczegółowa forma tej metody, GoogleMap.animateCamera(cameraUpdate, duration, callback), ma 3 argumenty:

cameraUpdate
CameraUpdate opisujący, gdzie przesunąć kamerę.
callback
Obiekt, który implementuje interfejs GoogleMap.CancellableCallback. Ten uogólniony interfejs do obsługi zadań definiuje 2 metody: `onCancel()` i `onFinished()`. W przypadku animacji metody te są wywoływane w tych okolicznościach:
onFinish()
Wywoływana, jeśli animacja zostanie ukończona bez przerw.
onCancel()

Wywoływana, gdy animacja zostanie przerwana przez wywołanie metody stopAnimation() lub rozpoczęcie nowego ruchu kamery.

Może się tak też zdarzyć, jeśli zadzwonisz pod numer GoogleMap.stopAnimation().

duration
Pożądany czas trwania animacji w milisekundach jako int.

Poniższe fragmenty kodu ilustrują niektóre 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));