Dodawanie znaczników i animacji do fotorealistycznej mapy 3D

1. Zanim zaczniesz

Z tego samouczka dowiesz się, jak dodawać znaczniki 3D i nadawać im styl w aplikacji. Dowiesz się też, jak animować aplikację, przelatując nad określonymi lokalizacjami i wokół nich.

Ten samouczek rozwija zagadnienia omówione w pierwszym codelab. Jeśli jeszcze tego nie zrobiłeś/nie zrobiłaś, ukończ to ćwiczenie, aby zdobyć podstawową wiedzę potrzebną do korzystania z tej aplikacji.

Co musisz zrobić

„Pełna mapa ze znacznikami.

Aplikacja ta zawiera przegląd najważniejszych biur Google w Europie. Użytkownicy mogą wybrać biuro, obejrzeć je z bliska, a następnie oddalić, aby powrócić do widoku ogólnego. Te funkcje, które są często dostępne w aplikacjach do podróży i zwiedzania, zapewniają użytkownikom bardziej wciągające wrażenia.

W tym ćwiczeniu utworzysz aplikację internetową 3D, która:

  • Dynamicznie wczytuje interfejs Maps JavaScript API.
  • Dodaje do mapy znaczniki 3D.
  • Styluje znaczniki za pomocą plików SVG.
  • Dodaliśmy możliwość przemieszczania się do znaczników i wokół nich.
  • Przekształca lokalizacje z kodu w tablicę.

Czego się nauczysz

  • Jak działają znaczniki
  • Jak stylizować znaczniki
  • Jak działa animacja z wbudowanymi funkcjami.
  • Umiejscowienie aparatu w porównaniu z miejscem docelowym w celu lepszego kadrowania.
  • przydatne porady dotyczące ustawiania parametrów aparatu, aby lepiej kadrować obiekty;

Wymagania wstępne

Aby ukończyć to ćwiczenie, musisz zapoznać się z tymi informacjami. Jeśli znasz już Google Maps Platform, przejdź do Codelab.

Wymagane usługi Google Maps Platform

W tym Codelab użyjesz tych usług Google Maps Platform:

  • Maps JavaScript API

Inne wymagania dotyczące tego ćwiczenia

Aby ukończyć to ćwiczenie, potrzebujesz tych kont, usług i narzędzi:

  • Konto Google Cloud z włączonymi płatnościami.
  • Klucz interfejsu API Google Maps Platform z włączonym interfejsem Maps JavaScript API.
  • podstawy JavaScriptu, HTML-a i CSS-a;
  • Edytor tekstu lub IDE, aby zapisać edytowany plik i go wyświetlić.
  • przeglądarka internetowa do wyświetlania pliku podczas pracy.

2. Konfiguracja

Konfigurowanie Google Maps Platform

Jeśli nie masz jeszcze konta Google Cloud Platform ani projektu z włączonymi płatnościami, zapoznaj się z artykułem Pierwsze kroki z Google Maps Platform, aby utworzyć konto rozliczeniowe i projekt.

  1. W konsoli Google Cloud kliknij menu projektu i wybierz projekt, którego chcesz użyć w tym CodeLab.

  1. Włącz interfejsy API i pakiety SDK Google Maps Platform wymagane w tym laboratorium kodu na platformie Google Cloud Marketplace. Aby to zrobić, wykonaj czynności opisane w tym filmie lub w tej dokumentacji.
  2. Wygeneruj klucz interfejsu API na stronie Dane logowania w konsoli Cloud. Możesz wykonać czynności opisane w tym filmie lub w tej dokumentacji. Wszystkie żądania do Google Maps Platform wymagają klucza interfejsu API.

3. Prosta kula ziemska

Aby rozpocząć tworzenie aplikacji, musisz najpierw skonfigurować jej podstawy. W efekcie otrzymasz widok „niebieskiej kuli”, czyli Ziemię w jej najbardziej podstawowej formie, jak na obrazku:

„Obraz przedstawiający kulę ziemską w jej początkowej konfiguracji.

Dodawanie kodu strony startowej

Aby dodać globusa do witryny, musisz dodać do strony podany niżej kod. Spowoduje to dodanie sekcji dla ładowarki interfejsu Maps JavaScript API i funkcji init, która tworzy element Mapy 3D na stronie, na której dodasz kod znaczników.

Pamiętaj, aby dodać na stronie swój klucz (utworz go w sekcji konfiguracji). W przeciwnym razie element 3D nie będzie można zainicjować.

<!DOCTYPE html>
<html>
   <head>
       <title>Step 1 - Simple Globe</title>
       <style>
           body {
               height: 100vh;
               margin: 0;
           }
       </style>
   </head>

   <body>
       <script>
           (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
               key: "<INSERT API KEY>",
               v: "alpha",
               // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
               // Add other bootstrap parameters as needed, using camel case.
           });
       </script>
       <script>
           let map3D = null;

           async function init() {
               const { Map3DElement, MapMode } = await google.maps.importLibrary("maps3d");

               map3D = new Map3DElement({
                   mode: MapMode.HYBRID,
               });

               document.body.append(map3D);
           }
           init();
       </script>
   </body>
</html>

Po wykonaniu tych czynności możesz zacząć kadrować interesujące Cię miejsce. Zrobisz to w następnym kroku.

4. Widok pierwszej klatki

Po utworzeniu mapy z widokiem kuli ziemskiej kolejnym krokiem jest określenie prawidłowej lokalizacji początkowej. Dzięki temu użytkownik może szybko sprawdzić, gdzie pracuje.

W tym przykładzie skupiamy się na biurach Google w Europie, ale możesz zastosować tę metodę w dowolnej lokalizacji na całym świecie – od całego kraju po jeden blok miejski. Szybkość i elastyczność produktu umożliwiają skalowanie aplikacji z globalnej na lokalną z minimalnymi zmianami kodu.

Zaczniesz od kadrowania, aby mapa 3D wyglądała tak:

„Globus z Europe w środku.

Ustaw kamerę na Europę

Aby uzyskać wyświetlanie zgodne z wyświetlanym obrazem, musisz prawidłowo ustawić wyświetlacz, tak jakbyś ustawiał kamerę w przestrzeni, aby patrzeć w dół na daną lokalizację.

W tym celu można użyć kilku parametrów w sterowaniu mapą do ustawienia szczegółów kamery. Na diagramie widać, jak parametry współdziałają w „rzeczywistym” świecie. Dotyczy to punktu, na który patrzy kamera, oraz odległości od miejsca, w którym się znajdujesz (zakres). Musisz też ustawić przechylenie perspektywy kamery (w przeciwnym razie będziesz patrzeć prosto na Ziemię).

„Zdjęcie przedstawiające parametry aparatu.

Ostatnie ustawienie, kierunek, określa kierunek kamery. Jest ona mierzona jako odchylenie od kierunku północnego. Te wartości są stosowane do elementu mapy 3D jako obiektu do konfigurowania początkowego wyświetlania. Możesz to zobaczyć w kodzie w zaktualizowanym konstruktorze elementu 3D.

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.HYBRID
});

Przechwytywanie parametrów aparatu

Ustawienie kadru na mapie 3D wymaga precyzyjnego umieszczenia kamery, co może być trudne do osiągnięcia za pomocą samego kodu. Aby uprościć ten proces, skorzystaj z tego przydatnego rozwiązania: dodaj do strony funkcję, która rejestruje parametry kamery po kliknięciu wymaganego widoku. Parametry zostaną przesłane do konsoli i będą gotowe do skopiowania do ustawień aparatu obiektu.

Kod, którego możesz użyć później, znajdziesz w przykładowej stronie. Jest on dodany do przykładowej strony, ale nie będzie widoczny na kolejnych stronach, ponieważ nie jest potrzebny w ramach Codelab. Warto jednak o nim pamiętać, jeśli chcesz tworzyć bardziej wciągające prezentacje dzięki lepszemu ustawieniu kamery.

map3D.addEventListener('gmp-click', (event) => {
   console.log("camera: { center: { lat: " + map3D.center.lat + ", lng : " + map3D.center.lng + ", altitude: " + map3D.center.altitude + " }, range: " + map3D.range + ", tilt: " + map3D.tilt + " ,heading: " + map3D.heading + ", }");
   console.log("{ lat: " + event.position.lat + ", lng : " + event.position.lng + ", altitude: " + event.position.altitude + " }");
   // Stop the camera animation when the map is clicked.
   map3D.stopCameraAnimation();
});

Zwróć uwagę na użycie funkcji stopCameraAnimation. Jeśli strona powiększa lub obraca się, przydaje się możliwość zatrzymania animacji, aby w danym momencie uchwycić pożądaną lokalizację na ekranie. Ten fragment kodu umożliwia to. Więcej informacji znajdziesz w dokumentacji stopCameraAnimation.

Przykład danych wyjściowych z kliknięcia, jak widać na konsoli.

camera: { center: { lat: 51.39870122020001, lng : -0.08573187165829443, altitude: 51.66845062662254 }, range: 716.4743880553578, tilt: 50.5766672986501 ,heading: -1.048260134782318, }
step2.html:40 { lat: 51.398158351120536, lng : -0.08561139388593597, altitude: 51.860469133677626 }

Tekst z aparatu może być używany jako dane wejściowe w formacie JSON w różnych obiektach na mapach 3D. Drugim wyjściem jest rzeczywista lokalizacja punktu, w którym nastąpiło kliknięcie. Jest ona przydatna do tworzenia punktów lub do pozycjonowania znaczników.

Po prawidłowym kadrowaniu strony możesz dodać znaczniki. Aby dowiedzieć się, jak to zrobić, przejdź do następnego kroku.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

<!DOCTYPE html>
<html>

<head>
   <title>Step 2 - Europe View</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
<script>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode } = await google.maps.importLibrary("maps3d");

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.HYBRID,
            });

           map3D.addEventListener('gmp-click', (event) => {
               console.log("camera: { center: { lat: " + map3D.center.lat + ", lng : " + map3D.center.lng + ", altitude: " + map3D.center.altitude + " }, range: " + map3D.range + ", tilt: " + map3D.tilt + " ,heading: " + map3D.heading + ", }");
               console.log("{ lat: " + event.position.lat + ", lng : " + event.position.lng + ", altitude: " + event.position.altitude + " }");

               map3D.stopCameraAnimation();
           });

           document.body.append(map3D);
       }
       init();
   </script>

</body>

</html>

5. Prosty znacznik

Z tej sekcji dowiesz się, jak dodać pierwszy znacznik. Najpierw poznasz ogólne informacje o markerach.

Mapy 3D umożliwiają tworzenie 2 różnych klas znaczników: Marker3DElementMarker3DInteractiveElement. Wybór klasy zależy od tego, czy chcesz umożliwić klikanie znaczników. Poza tym są one zasadniczo takie same, więc najpierw utwórz Marker3DElement, a potem w kolejnych krokach „uaktualnij” go do Marker3DInteractiveElement.

Pełne rozwiązanie tego etapu znajdziesz tutaj:

„Globus ze znacznikiem pokazującym zakończony krok.

Dodaj trochę wysokości do znaczników

Najpierw musisz wiedzieć, że znaczniki są trójwymiarowe, tak jak wszystko inne na mapie 3D. Oznacza to, że lokalizacja może mieć wysokość (wysokość n.p.m.), która może być reprezentowana jako pozycja względem poziomu morza, podłoża lub siatki albo może być ograniczona do podłoża i ignorować wysokość n.p.m. Więcej informacji znajdziesz w sekcji Altitude constants w dokumentacji AltitudeMode.

Możesz też ustawić, czy znacznik ma być wytłoczony, czy nie, za pomocą wartości wytłoczony. Określa to, czy znacznik będzie miał małą linię rysowaną w dół, aby pokazać rzeczywistą pozycję w stosunku do wysokości. Jest to przydatne do wskazywania punktów na ziemi. Przykładem jest lokalizacja Google w Wielkiej Brytanii. Obie są wytłoczone i mają ustawioną pozycję na Wysokość bezwzględna. Pierwszy na 75 metrach, a drugi na 125 metrach.

znacznik na 75 metrach,

Oznaczenie na 125 metrach

Wysokość 75 metrów.

Wysokość 125 metrów.

Ukrywanie i pokazywanie znaczników z zasłonięciem i kolizją

W naszym pokazie nie jest to ważne, ponieważ pozycje są od siebie dość oddalone, ale w przypadku znaczników, które mogą się na siebie nakładać lub znajdować za budynkami, możesz kontrolować, co się z nimi dzieje, za pomocą wartości collisionBehavior lub drawsWhenOccluded.

W przypadku zachowania w przypadku kolizji dostępne są te opcje:

  • REQUIRED: (wartość domyślna) zawsze wyświetlaj znacznik niezależnie od kolizji.
  • OPTIONAL_AND_HIDES_LOWER_PRIORITY Wyświetlaj znacznik tylko wtedy, gdy nie nakłada się on na inne znaczniki. Jeśli 2 takie znaczniki nakładają się na siebie, wyświetla się ten z wyższym zIndex. Jeśli mają ten sam atrybuty zIndex, wyświetlana jest pozycja z niższym pionowym położeniem ekranu.
  • REQUIRED_AND_HIDES_OPTIONALZawsze wyświetlaj znacznik niezależnie od kolizji i ukrywanie wszelkich OPTIONAL_AND_HIDES_LOWER_PRIORITY znaczników lub etykiet, które nakładają się na znacznik.

Różnice w sposobie wyświetlania znaczników na podstawie zdefiniowanego zachowania w przypadku kolizji przedstawiono na obrazach. Gdy ustawisz wartość REQUIRED, będą widoczne wszystkie znaczniki, ale jeśli użyjesz wartości REQUIRED_AND_HIDES_OPTIONAL, będą widoczne tylko znaczniki znajdujące się niżej na ekranie (jeśli chcesz, możesz ustawić wartość zIndex, aby inne znaczniki były wyświetlane na górze).

znaczniki są wyświetlane zgodnie z wymaganiami,

znaczniki ukrywające inne znaczniki,

WYMAGANE

REQUIRED_AND_HIDES_OPTIONAL

W przypadku zasłonięcia możesz wybrać, czy znaczniki mają być wyświetlane za budynkami, czy nie. Pokazuje to poniższy obraz. Gdy parametr drawsWhenOccluded ma wartość Prawda, znaczniki są lekko przyciemnione, gdy są narysowane za budynkami. Gdy ma wartość Fałsz, znaczniki są ukryte, gdy znajdują się za budynkiem. Więcej informacji znajdziesz w tabeli poniżej:

Obraz przedstawiający mapę z ukrytymi znacznikami

Obraz przedstawiający mapę z zasłoniętymi znacznikami

drawsWhenOccluded : false

drawsWhenOccluded : true

Jak już wspomnieliśmy, znaczniki ukryte przez kolizję będą wyświetlane przyciemnione, jeśli dozwolone jest rysowanie zasłoniętych znaczników. Na obrazie widać niektóre znaczniki ukryte przez budynki i inne znaczniki.

„Zdjęcie przedstawiające kilka znaczników i efekt zasłonięcia.

Więcej informacji znajdziesz w przykładzie zachowania w przypadku kolizji na mapie 2D.

Wyczyść obszar roboczy

Teraz nadszedł czas na utworzenie pierwszego znacznika. Aby użytkownik skupiał się na znacznikach, możesz wyłączyć domyślne etykiety na mapie 3D.

Ustaw wartość mode elementu mapy 3D na SATELLITE.

Więcej informacji znajdziesz w sekcji Tryb.

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.SATELLITE
});

W efekcie otrzymujemy taką mapę 3D:

„Obraz Europy bez granic i tekstu.

Dodawanie pierwszego znacznika

Teraz, gdy masz czyste tworzywo, możesz dodać pierwszy znacznik. Kluczowe parametry to pozycja i etykieta.

Aby dodać znacznik, ustaw jego pozycję. Możesz też dodać etykietę, która pojawia się nad znacznikiem, oraz inne elementy zgodnie z opisem w dokumentacji Marker3DElement.

Aby dodać nasz znacznik, dodaj poniższy kod po wierszu, który ukrywa domyślne etykiety:

const marker = new Marker3DElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

map3D.append(marker);

Po utworzeniu znacznika dodaj go do mapy 3D, używając metody append. Pamiętaj, że znaczniki są przechowywane jako tablica elementów podrzędnych na mapie 3D. Aby zmodyfikować znacznik, musisz uzyskać do niego dostęp za pomocą tej tablicy.

Upewnij się, że interfejs Marker3DElement jest wczytywany z interfejsu Maps JavaScript API. Aby to zrobić, dodaj go do listy bibliotek podczas wczytywania interfejsu API.

const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");

Po załadowaniu strony będzie widoczna cała Europa z oznacznikiem nad biurem w Londynie. Jak widać na animacji, możesz ręcznie przybliżyć widok, aby zobaczyć znacznik nad utworzoną lokalizacją.

„Animacja pokazująca ręczne przybliżanie widoku do Google UK.

Po załadowaniu pierwszego znacznika możesz go uatrakcyjnić.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

<!DOCTYPE html>
<html>

<head>
   <title>Step 3 - Simple Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       async function init() {
            const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");

            map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
            });

           const marker = new Marker3DElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });
           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

6. znacznik SVG,

W tym kroku poprawisz wygląd znacznika, dodając do niego flagę kraju, w którym się znajduje. Aby dowiedzieć się, jak to zrobić, musisz zapoznać się z elementem PinElement.

W efekcie będzie on wyglądać tak:

„Obraz z pisakiem z flagą Wielkiej Brytanii”

Podstawowe dostosowywanie za pomocą elementu PinElement

Jednym z elementów udostępnianych znacznikom w interfejsie JavaScript API (na mapach 2D i 3D) jest element PinElement. Podczas dodawania Marker3DElement do Map3DElement dodasz element PinElement do elementu Marker3DElement jako element podrzędny.

Element PinElement umożliwia na podstawowym poziomie zmianę normalnego znacznika, aby ustawić kolor obramowania, kolor punktu wewnętrznego (lub glifu) oraz kolor tła. Możesz je zobaczyć na obrazie przedstawiającym znacznik 2D.

„Obraz z opcjami dostosowania znacznika”

Rozmiar znacznika możesz też ustawić za pomocą elementu, ustawiając jego wartość skali (wartość większa niż 1 oznacza większy rozmiar, a mniejsza – mniejszy).

Możesz też zastąpić glif obrazem lub plikiem SVG, jeśli chcesz nadać pinezce niestandardowy wygląd, ale zachować standardowy wygląd pinezy PinElement.

Beyond PinElements

W tym kroku zaktualizujesz standardowy znacznik PinElement, używając flagi SVG i różnych kolorów. Warto jednak wiedzieć, że możesz całkowicie zmienić wygląd znacznika, tak aby nie przypominał nawet pinezki na mapie. W Markerze możesz też umieszczać nowe grafiki za pomocą szablonów, takich jak HTMLImageElement i SVGElement. Więcej informacji na ten temat znajdziesz w dokumentacji Marker3DElement-Slots.

Aby zobaczyć, co jest możliwe, zapoznaj się z poniższymi przykładami stylizacji znaczników za pomocą różnych technik.

Obraz przedstawiający podstawowe dostosowywanie znaczników.

Obraz przedstawiający złożoną personalizację znacznika.

znaczniki z podstawowym dostosowywaniem za pomocą PinElement (patrz próbki);

znaczniki z zaawansowanymi opcjami dostosowywania w ramach szablonu za pomocą SVG i obrazów (patrz przykłady);

Dodaj PinElement

Aby zmienić wygląd znacznika, musisz najpierw dodać do strony bibliotekę PinElement. Aby to zrobić, dodaj ten wiersz kodu po zaimportowaniu biblioteki maps3d:

const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");
const { PinElement } = await google.maps.importLibrary('marker');

Teraz, gdy element jest załadowany, można utworzyć i odwoływać się do elementu PinElement. Sprawdź kod, dodaj go między miejscami, w których tworzony jest znacznik, i dołącz znacznik do mapy 3D.

const marker = new Marker3DElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

const markerPin = new PinElement({
   "background": 'white',
   "glyph": new URL(base + '/images/gb.svg'),
   "scale": 1.0,
});
marker.append(markerPin);

map3D.append(marker);

Ponieważ nie wczytujesz tylko podstawowego pinu, musisz wykonać kilka czynności, a nie tylko skonfigurować PinElement z powiązanym kolorem tła i skalą.

Najpierw należy utworzyć obraz svg dla ikony flagi, w tym przypadku flagi Zjednoczonego Królestwa. Możesz je pobrać z kolekcji takiej jak ta na stronie https://flagicons.lipis.dev/.

Gdy masz ikonę, możesz ją umieścić w miejscu, w którym może ją znaleźć witryna. W tym przypadku możesz zakodować na stałe lokalizację obrazu lub użyć bieżącej lokalizacji witryny jako stubu katalogu, jak pokazano tutaj za pomocą zmiennej bazowej. Następnie możesz połączyć tę lokalizację na serwerze z odpowiednią flagą, która w tym przypadku znajduje się w '/images/gb.svg'.

Spowoduje to utworzenie elementu PinElement, który wygląda tak:

„Marker z symbolem flagi Union Jack.

Gdy flaga i kod zostaną umieszczone we właściwych miejscach, mapa 3D powinna wyglądać tak:

„Powiększenie do nowego znacznika.

Teraz nasz znacznik jest gotowy. Możesz go też zmienić, aby można było go kliknąć i dodać interaktywność. Zrobisz to w kolejnym kroku.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

Pamiętaj też, że musisz pobrać plik SVG (lub PNG) z flagą i zapisać go w katalogu, który może być znaleziony przez Twoją stronę (tutaj jest zapisany w folderze images).

<!DOCTYPE html>
<html>

<head>
   <title>Step 4 - SVG Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

7. Znacznik interaktywny

W ostatnim kroku dodano na stronie znacznik, który jednak nie ma żadnej funkcji oprócz estetycznej. W dalszym ciągu musisz wchodzić w interakcję z mapą 3D w taki sam sposób. Następnym krokiem jest dodanie możliwości wykonania jakiejś czynności po kliknięciu znacznika, co pozwoli mu reagować na interakcje użytkownika.

Aby dodać tę funkcję, musisz przekształcić element Marker3DElement w element Marker3DInteractiveElement. Otrzymasz w ten sposób podobną stronę, ale po kliknięciu znacznika pojawi się alert, który będzie wyglądał mniej więcej tak:

„Obraz pokazujący odpowiedź po kliknięciu.

Najpierw zmień klasę znacznika

Aby dodać interaktywność do znacznika, musisz się upewnić, że używa on odpowiedniej klasy. Potrzebna jest klasa Marker3DInteractiveElement, ale ponieważ jest ona rozszerzeniem klasy Marker3DElement, nie musisz nic robić oprócz załadowania nowej klasy i zmiany nazwy klasy w konstruktorze.

const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
const { PinElement } = await google.maps.importLibrary('marker');

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.SATELLITE,
});

const marker = new Marker3DInteractiveElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

Następnie dodaj zdarzenie kliknięcia do znacznika.

Następnie dodaj do znacznika zdarzenie kliknięcia, aby obsłużyć interakcję użytkownika i na nią zareagować. W fragmentie kodu widać, że do znacznika dodano zdarzenie kliknięcia. W tym przypadku uruchamia się alert i wyświetla tekst, który wyświetla etykietę ze znacznika, uzyskaną z celu wywołanego zdarzenia, co pozwala nam uzyskać dostęp do właściwości etykiety. Dodaj ten kod do aplikacji tuż po utworzeniu znacznika.

marker.addEventListener('gmp-click', (event) => {
   alert('You clicked on : ' + event.target.label);
   event.stopPropagation();
});

Uwaga: zdarzenie stopPropagation służy do zapewnienia, że wszystkie inne słuchacze kliknięć w steku są wywoływane na obiektach podrzędnych, takich jak główne tworzywo mapy 3D.

Gdy teraz uruchomisz aplikację, powinieneś uzyskać taki wynik:

„Obraz pokazujący odpowiedź po kliknięciu.

Dzięki możliwości wykonania jakiejś czynności po kliknięciu znacznika możesz teraz dodać na stronie animację.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

<!DOCTYPE html>
<html>

<head>
   <title>Step 5 - Interactive Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               alert('You clicked on : ' + event.target.label);
               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

8. Przejdź do

W tym kroku klikniesz znacznik dodanej animacji, aby przenieść się do jej lokalizacji. Możesz to sprawdzić tutaj.

„Animacja pokazująca kliknięcie znacznika i przejście do lokalizacji.

Animowanie za pomocą metody flyCameraTo

Aby dodać to na stronie, użyj metody flyCameraTo w Mapach 3D. Kamera animuje się od Twojej lokalizacji do lokalizacji, którą chcesz wyświetlić, interpolując między tymi dwoma punktami i animując lot w ramach mapy 3D.

Gdy używasz metody flyCameraTo, musisz podać FlyToAnimationOptions, która ma 2 właściwości: endCamera, czyli lokalizację, na którą ma wskazywać kamera na końcu animacji, oraz durationMillis, czyli czas w milisekundach, jaki zajmie przejście.

W tym przykładzie ustaw kamerę tak, aby obserwowała budynek, który jest pozycją znacznika, z nachyleniem 65 stopni, zasięgiem 500 metrów i kierunkiem na północ o 0 stopniach. Ustaw czas animacji na 12 500 ms (12,5 s).

Zastąp na stronie bieżące zdarzenie alertu fragmentem kodu flyCameraTo:

marker.addEventListener('gmp-click', (event) => {
   map3D.flyCameraTo({
       endCamera: {
           center: marker.position,
           tilt: 65,
           range: 500,
           heading: 0,
       },
       durationMillis: 12500,
   });

   event.stopPropagation();
});

To wszystko. Teraz możesz odświeżyć stronę, kliknąć znacznik i przenieść się do Google UK, jak pokazano w animacji:

„Animacja pokazująca kliknięcie znacznika i przejście do lokalizacji.

W tym kroku dodałeś klikalny znacznik, który przenosi kamerę do lokalizacji znacznika. W następnym kroku dodasz możliwość przelotu kamery wokół punktu, tak aby krążyła wokół tej lokalizacji.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

<!DOCTYPE html>
<html>

<head>
   <title>Step 6 - Zoom To</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               map3D.flyCameraTo({
                   endCamera: {
                       center: marker.position,
                       tilt: 65,
                       range: 500,
                       heading: 0,
                   },
                   durationMillis: 12500,
               });

               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

9. Oblot

Ostatnim elementem naszej animacji jest użycie metody flyCameraAround, aby utworzyć animację orbity wokół budynku. Na końcu animacja przeleci nad budynkiem, a potem okrąży go dookoła, jak pokazano na animacji. To jest prawdopodobnie trochę za szybki przykład, ale pokazuje, jak działa działanie bez zbędnego przedłużania. Możesz zmieniać czasy trwania, aż uzyskasz wartość, która Ci odpowiada.

„Animacja pokazująca kliknięcie znacznika, a następnie przelot do lokalizacji i po jej obwodzie.

Lećmy!

Metoda flyCameraAround jest podobna do funkcji flyCameraTo, ponieważ przyjmuje jako dane wejściowe kilka opcji, które określają, którą lokalizację ma okrążać, a także czas w milisekundach, jaki ma trwać obrót. Możesz też określić liczbę rotacji, które mogą wystąpić w określonym czasie. Wszystkie opcje znajdziesz w sekcji FlyAroundAnimationOptions.

Ale chwila!

W animacji możesz zobaczyć, jak animacja leci do lokalizacji, a następnie krąży wokół niej, łącząc animacje. Aby to zrobić, użyj zdarzenia gmp-animationend w mapach 3D, aby upewnić się, że bieżąca animacja została zakończona przed uruchomieniem następnej. Animacja powinna się odtwarzać tylko raz.

Zapoznaj się z kodem i wstaw go po kodzie dodanym w poprzedniej sekcji.

marker.addEventListener('gmp-click', (event) => {
   map3D.flyCameraTo({
       endCamera: {
           center: marker.position,
           tilt: 65,
           range: 500,
           heading: 0,
       },
       durationMillis: 5000,
   });

   map3D.addEventListener('gmp-animationend', () => {
       map3D.flyCameraAround({
           camera: {
               center: marker.position,
               tilt: 65,
               range: 500,
               heading: 0,
           },
           durationMillis: 5000,
           rounds: 1
       });
   }, { once: true });

   event.stopPropagation();
});

Dodanie możliwości nasłuchiwania zdarzenia gmp-animationend pozwala wywołać zdarzenie flyCameraAround. Ustawienie punktu wyjścia na taki sam, który został użyty w przypadku metody „fly to” w przypadku końcowej kamery, oznacza płynne przejście (aby nie powodować żadnych gwałtownych ruchów w nowej lokalizacji). Ponownie parametr durationMillis służy do kontrolowania czasu trwania animacji. W tym przypadku metoda przyjmuje też inną opcję, rounds, która jest ustawiona na 1.

Oznacza to, że kamera będzie obracać się wokół tego punktu raz na 5 sekund. Możesz eksperymentować z tymi wartościami, aby znaleźć te, które Ci odpowiadają.

W tym momencie animacja się zakończy, ale nie chcesz, aby zdarzenie gmp-animationend zostało wywołane ponownie za pomocą tego fragmentu kodu, ponieważ spowoduje to nieskończoną orbitę. Aby tego uniknąć, opcja dla słuchacza z ustawieniem once powinna być równa true. Oznacza to, że po zakończeniu zdarzenia zostanie ono usunięte, co zapobiegnie nieskończonej pętli.

Po dodaniu tego elementu możesz uruchomić rozwiązanie i zobaczyć animację, która teraz krąży wokół znacznika na końcu, jak pokazano na animacji:

„Animacja pokazująca latanie wokół znacznika.

W tym kroku masz teraz znacznik, który można kliknąć. Kamera przeleci do lokalizacji znacznika i obejdzie go. Na kolejnym etapie zaczniemy dodawać kolejne punkty i umożliwimy przełączanie się między nimi.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

<!DOCTYPE html>
<html>

<head>
   <title>Step 7 - Zoom Around</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               map3D.flyCameraTo({
                   endCamera: {
                       center: marker.position,
                       tilt: 65,
                       range: 500,
                       heading: 0,
                   },
                   durationMillis: 5000,
               });

               map3D.addEventListener('gmp-animationend', () => {
                   map3D.flyCameraAround({
                       camera: {
                           center: marker.position,
                           tilt: 65,
                           range: 500,
                           heading: 0,
                       },
                       durationMillis: 5000,
                       rounds: 1
                   });
               }, { once: true });

               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

10. Paryżu!

Londyn to wspaniały, ale samotny okaz na tej stronie. Zacznijmy więc dodawać nowe lokalizacje, zaczynając od Paryża. W tym celu można użyć tablicy, która będzie przechowywać wszystkie szczegóły dotyczące lokalizacji, a potem używać jej jako danych wejściowych do funkcji i zmiennych, które ustawiają parametry wyświetlania znacznika oraz przelotu do i wokół lokalizacji kamery. Jak już wspomnieliśmy, może ona się różnić od lokalizacji punktu znacznika, na przykład ze względu na kadrowanie budynku.

„Animacja pokazująca kliknięcie i przelot nad Francją w Google.

Tablica lokalizacji

Aby nie trzeba było kodować wszystkich szczegółów dotyczących konkretnej lokalizacji, takich jak widok kamery, punkt znacznika i opcje wyświetlania, możesz użyć małej tablicy obiektów JSON do przechowywania tych danych. Można go następnie zastosować podczas tworzenia i używania znaczników w aplikacji. W przykładowym fragmencie kodu widać, że zmienna o nazwie officeLocations służy do przechowywania tablicy.

Dodaj ten kod tuż przed funkcją init. Zwróć też uwagę, że zmienna podstawowa została przeniesiona poza funkcję init, aby można było jej używać we wszystkich lokalizacjach biur.

const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

const europeCamera = {
   center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
   range: 5814650,
   tilt: 33,
   heading: 4.36,
};

const officeLocations = [
   {
       "name": "Google France",
       "camera": {
           "center": { lat: 48.877276, lng: 2.329978, altitude: 48 },
           "range": 178,
           "tilt": 57.48,
           "heading": -17,
       },
       "point": { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       "pin": {
           "background": 'white',
           "glyph": new URL(base + '/images/fr.svg'),
           "scale": 1.0,
       },
   },
   {
       "name": "Google UK",
       "camera": {
           "center": { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           "range": 500,
           "tilt": 56.21672368296945,
           "heading": -31.15763027564165,
       },
       "point": { lat: 51.5332, lng: -0.1260, altitude: 75 },
       "pin": {
           "background": 'white',
           "glyph": new URL(base + '/images/gb.svg'),
           "scale": 1.0,
       },
   }]
       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

Każda lokalizacja biura ma te właściwości:

  • name :nazwa lokalizacji.
  • camera :początkowy widok, w którym można zobaczyć lokalizację i przemieszczać się po niej.
  • punkt : lokalizacja, w której ma się znajdować znacznik.
  • pin :informacje o kolorze i właściwościach znacznika

Inny kąt

Możesz zauważyć, że w przypadku Wielkiej Brytanii centrum kamery i punkt znacznika są takie same (poza wysokością), podczas gdy we Francji są różne. Dzieje się tak, ponieważ w przypadku lokalizacji we Francji znacznik musi znajdować się w innej lokalizacji niż początkowy widok z kamery, co pozwala uzyskać lepszy widok całego budynku podczas przelotu niż w przypadku użycia punktu znacznika.

Powrót do Europy

Jedną z funkcji posiadania większej liczby punktów jest to, że wymaga ona możliwości przemieszczania się między nimi. Możesz użyć menu, aby umożliwić wybór, ale w tym przykładzie kamera za każdym razem wraca do widoku europejskiego, aby umożliwić użytkownikowi wybranie innej lokalizacji.

Aby to zrobić, musisz zapisać początkowy widok w zmiennej, która pozwoli zresetować kamerę do widoku całej Europy. W tym przykładzie dodaj nową zmienną o nazwie europeCamera, aby przechowywać w niej dane na potrzeby późniejszego użycia.

Zaktualizuj funkcję init

Pierwszą zmianą, którą musisz wprowadzić, jest użycie obiektu europeCamera jako danych wejściowych podczas tworzenia obiektu Map3DElement.

Druga zmiana, którą musisz wprowadzić, to umieszczenie sekcji tworzenia znacznika w pętli, aby zaktualizować ją za pomocą parametrów przechowywanych w zmiennych. Możesz je zobaczyć w prezentowanym kodzie:

  • office.point :lokalizacja znacznika.
  • office.name :nazwa biura używana na etykiecie znacznika.
  • office.camera : początkowa lokalizacja kamery.
  • office.pin :opcje elementu PinElement dotyczące różnic w wyświetlaniu.

Nie zapomnij też pobrać pliku SVG lub obrazu z flagą Francji.

async function init() {
   const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
   const { PinElement } = await google.maps.importLibrary('marker');

   map3D = new Map3DElement({
       ...europeCamera,
       mode: MapMode.SATELLITE,
   });

   officeLocations.forEach(office => {
       const marker = new Marker3DInteractiveElement({
           position: office.point,
           label: office.name,
           altitudeMode: 'ABSOLUTE',
           extruded: true,
       });

       marker.addEventListener('gmp-click', (event) => {
           map3D.flyCameraTo({
               endCamera: office.camera,
               durationMillis: 5000,
           });

           map3D.addEventListener('gmp-animationend', () => {
               map3D.flyCameraAround({
                   camera: office.camera,
                   durationMillis: 5000,
                   rounds: 1
               });

               map3D.addEventListener('gmp-animationend', () => {
                   map3D.flyCameraTo({
                       endCamera: europeCamera,
                       durationMillis: 5000,
                   });
               }, { once: true });

           }, { once: true });

           event.stopPropagation();
       });

       const markerPin = new PinElement(office.pin);
       marker.append(markerPin);

       map3D.append(marker);
   });
   document.body.append(map3D);
}

Po animacji flyCameraAround dodano drugą funkcję gmp-animationend, aby obsłużyć powrót do widoku europejskiego za pomocą zapisanej zmiennej europeCamera. Jak widać na animacji:

„Animacja przelatująca między biurami we Francji i Wielkiej Brytanii.

Na tym etapie aplikacja została rozszerzona o 2 lokalizacje i możliwość przemieszczania się między nimi za pomocą animacji i tablicy lokalizacji. W następnym etapie do tablicy zostanie dodana reszta lokalizacji biur.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

Pamiętaj też, że musisz pobrać plik SVG z flagą (lub pliki PNG) i przechowywać je w katalogu, który może być znaleziony przez Twoją stronę (tutaj są one przechowywane w folderze images).

<!DOCTYPE html>
<html>

<head>
   <title>Step 8 - Paris!</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

       const officeLocations = [
           {
               "name": "Google France",
               "camera": {
                   "center": { lat: 48.877276, lng: 2.329978, altitude: 48 },
                   "range": 178,
                   "tilt": 57.48,
                   "heading": -17,
               },
               "point": { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
               "pin": {
                   "background": 'white',
                   "glyph": new URL(base + '/images/fr.svg'),
                   "scale": 1.0,
               },
           },
           {
               "name": "Google UK",
               "camera": {
                   "center": { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
                   "range": 500,
                   "tilt": 56.21672368296945,
                   "heading": -31.15763027564165,
               },
               "point": { lat: 51.5332, lng: -0.1260, altitude: 75 },
               "pin": {
                   "background": 'white',
                   "glyph": new URL(base + '/images/gb.svg'),
                   "scale": 1.0,
               },
           }]

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           officeLocations.forEach(office => {
               const marker = new Marker3DInteractiveElement({
                   position: office.point,
                   label: office.name,
                   altitudeMode: 'ABSOLUTE',
                   extruded: true,
               });

               marker.addEventListener('gmp-click', (event) => {
                   map3D.flyCameraTo({
                       endCamera: office.camera,
                       durationMillis: 5000,
                   });

                   map3D.addEventListener('gmp-animationend', () => {
                       map3D.flyCameraAround({
                           camera: office.camera,
                           durationMillis: 5000,
                           rounds: 1
                       });

                       map3D.addEventListener('gmp-animationend', () => {
                           map3D.flyCameraTo({
                               endCamera: europeCamera,
                               durationMillis: 5000,
                           });
                       }, { once: true });

                   }, { once: true });

                   event.stopPropagation();
               });

               const markerPin = new PinElement(office.pin);
               marker.append(markerPin);

               map3D.append(marker);
           });
           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

11. Więcej miejsc

Aplikacja ma już wszystkie potrzebne funkcje, ale mapa 3D nadal wygląda trochę skąpo. Dodaj więc jeszcze kilka lokalizacji, aby ją nieco zapełnić. Dzięki zastosowaniu tablicy możesz łatwo wypełniać nowe lokalizacje, przypisując do nich unikalne znaczniki. Ostatnim krokiem jest dodawanie znaczników, aż do uzyskania widoku przedstawionego poniżej.

„Zdjęcie przedstawiające wszystkie biura.

dodawanie kolejnych znaczników,

Google ma wiele biur w różnych krajach Europy, dlatego dodamy niektóre z nich do mapy. Wystarczy zaktualizować tablicę. Może on pochodzić z usługi internetowej lub być udostępniany z pliku stałego gdzieś w innym miejscu. W naszym przypadku ze względów praktycznych będzie on przechowywany na tej samej stronie.

Możesz dodać dowolną liczbę znaczników, które są pobierane przez stronę, a następnie automatycznie dodawane do widoku. Pamiętaj, aby pobrać odpowiednie flagi i zapisać je w katalogu images (lub w dowolnym innym dogodnym miejscu).

const officeLocations = [
   {
       name: "Google France",
       camera: {
           center: { lat: 48.877276, lng: 2.329978, altitude: 48 },
           range: 178,
           tilt: 57.48,
           heading: -17,
       },
       point: { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/fr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google UK",
       camera: {
           center: { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 51.5332, lng: -0.1260, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gb.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Belgium",
       camera: {
           center: { lat: 50.83930408436509, lng: 4.38052394507952, altitude: 64.38932203802196},
           range: 466.62899893119175,
           tilt: 43.61569474716178,
           heading: 51.805907046332074,
       },
       point: { lat: 50.8392653, lng: 4.3808751, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/be.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Czechia",
       camera: {
           center: {
               lat: 50.07004093853976,
               lng: 14.402871475443956,
               altitude: 223.39574818495532
           },
           range: 522.0365799222782,
           tilt: 62.39511972890614,
           heading: -39.150149539328304,
       },
       point: { lat: 50.0703122, lng: 14.402668199999999, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/cz.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Denmark",
       details: "2, Sankt Petri Passage 5, 1165 København",
       camera: {
           center: {
               lat: 55.680359539635866,
               lng: 12.570460204526002,
               altitude: 30.447654757346044
           },
           range: 334.8786935049066,
           tilt: 55.38819319004654,
           heading: 149.63867461295067,
       },
       point: { lat: 55.6804504, lng: 12.570279099999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/dk.svg'),
           scale: 1.0,
       },
   },
   ,
   {
       name: "Google Greece",
       camera: {
           center: {
               lat: 38.038634694028055,
               lng: 23.802924946201266,
               altitude: 196.45884670344995
           },
           range: 343.57226336076565,
           tilt: 54.97375927639567,
           heading: -33.26775344055724,
       },
       point: { lat: 38.038619, lng: 23.8031622, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Germany",
       camera: {
           center: {
               lat: 53.55397683312404,
               lng: 9.986350507286808,
               altitude: 44.83610870143956
           },
           range: 375.3474077822466,
           tilt: 71.35078443829818,
           heading: -160.76930098951416,
       },
       point: { lat: 53.5540227, lng: 9.9863, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/de.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Ireland",
       camera: {
           center: { lat: 53.339816899999995, lng: -6.2362644, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 53.339816899999995, lng: -6.2362644, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ie.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Italy",
       camera: {
           center: {
               lat: 45.486361346538224,
               lng: 9.18995496294455,
               altitude: 138.55834058400072
           },
           range: 694.9398023590038,
           tilt: 57.822470255679114,
           heading: 84.10194883488619,
       },
       point: { lat: 45.4863064, lng: 9.1894762, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/it.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Lithuania",
       camera: {
           center: {
               lat: 54.698040606567965,
               lng: 25.30965338542576,
               altitude: 111.80276944294413
           },
           range: 412.5808304977545,
           tilt: 43.50793332082195,
           heading: -29.181098269421028,
       },
       point: { lat: 54.6981204, lng: 25.3098617, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/at.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Netherlands",
       camera: {
           center: {
               lat: 52.33773837150874,
               lng: 4.871754560171063,
               altitude: 53.68063996154723
           },
           range: 473.1982259177312,
           tilt: 56.216523350388634,
           heading: 71.78252318033718,
       },
       point: { lat: 52.337801, lng: 4.872065999999999, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/nl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Norway",
       camera: {
           center: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/no.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Poland",
       camera: {
           center: { lat: 52.22844380000001, lng: 20.9851819, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 52.22844380000001, lng: 20.9851819, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Portugal",
       camera: {
           center: {
               lat: 38.7240122810727,
               lng: -9.150628263172639,
               altitude: 55.299662291551044
           },
           range: 337.7474313328639,
           tilt: 56.79772652682846,
           heading: 176.0722118222208,
       },
       point: { lat: 38.723915999999996, lng: -9.150629, altitude: 35 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pt.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Romania",
       camera: {
           center: {
               lat: 44.43076650172983,
               lng: 26.109700164718586,
               altitude: 125.57895810814505
           },
           range: 364.25249956711923,
           tilt: 38.517539223834326,
           heading: -38.81294924429363,
       },
       point: { lat: 44.4309897, lng: 26.1095719, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ro.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Spain",
       camera: {
           center: {
               lat: 40.450078762608875,
               lng: -3.6930085080020856,
               altitude: 753.6446342341894
           },
           range: 845.7279793010093,
           tilt: 46.752510050599746,
           heading: 4.718779524265234,
       },
       point: { lat: 40.450294199999995, lng: -3.6927915, altitude: 175 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/es.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Sweden",
       camera: {
           center: {
               lat: 59.33313751316038,
               lng: 18.054618219238293,
               altitude: 16.728213706832868
           },
           range: 377.5210725830039,
           tilt: 63.59478230626709,
           heading: 98.53138488367703,
       },
       point: { lat: 59.3332093, lng: 18.0536386, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/se.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Switzerland",
       camera: {
           center: {
               lat: 47.365411056285275,
               lng: 8.525063594405356,
               altitude: 419.2348376754488
           },
           range: 166.74918737631742,
           tilt: 59.31431457129067,
           heading: -32.620415961949206,
       },
       point: { lat: 47.365452, lng: 8.5249253, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ch.svg'),
           scale: 1.0,
       },
   }
]

Po wykonaniu tych czynności powinna pojawić się pełna strona, jak na obrazku, która umożliwia użytkownikowi kliknięcie dowolnej lokalizacji, przelot nad nią i powrót.

„Amination latający między biurami w Hiszpanii i Szwecji.

Gratulacje! Zakończyliśmy już zajęcia z programowania. W następnej sekcji podsumujemy to, czego się nauczyliście, i zaproponujemy inne nowości do wypróbowania.

Rozwiązanie dotyczące sekcji

W tym kroku gotowa strona jest podawana jako rozwiązanie, które pozwoli Ci zweryfikować implementację. (jeśli kopiujesz, upewnij się, że używasz własnego klucza API).

Pamiętaj też, że musisz pobrać plik SVG z flagą (lub pliki PNG) i przechowywać je w katalogu, który może być znaleziony przez Twoją stronę (tutaj są one przechowywane w folderze images).

<!DOCTYPE html>
<html>

<head>
   <title>Step 9 - More Places!</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <script>
       (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
           key: "<INSERT API KEY>",
           v: "alpha",
           // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
           // Add other bootstrap parameters as needed, using camel case.
       });
   </script>
   <script>
       let map3D = null;

       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

const officeLocations = [
   {
       name: "Google France",
       details: "8 Rue de Londres, 75009 Paris, France",
       camera: {
           center: { lat: 48.877276, lng: 2.329978, altitude: 48 },
           range: 178,
           tilt: 57.48,
           heading: -17,
       },
       point: { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/fr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google UK",
       details: "6 Pancras Square, London N1C 4AG, UK",
       camera: {
           center: { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 51.5332, lng: -0.1260, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gb.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Belgium",
       details: "Chau. d'Etterbeek 180, 1040 Brussel",
       camera: {
           center: { lat: 50.83930408436509, lng: 4.38052394507952, altitude: 64.38932203802196},
           range: 466.62899893119175,
           tilt: 43.61569474716178,
           heading: 51.805907046332074,
       },
       point: { lat: 50.8392653, lng: 4.3808751, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/be.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Czechia",
       details: "Stroupežnického 3191/17, 150 00 Praha 5-Smíchov",
       camera: {
           center: {
               lat: 50.07004093853976,
               lng: 14.402871475443956,
               altitude: 223.39574818495532
           },
           range: 522.0365799222782,
           tilt: 62.39511972890614,
           heading: -39.150149539328304,
       },
       point: { lat: 50.0703122, lng: 14.402668199999999, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/cz.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Denmark",
       details: "2, Sankt Petri Passage 5, 1165 København",
       camera: {
           center: {
               lat: 55.680359539635866,
               lng: 12.570460204526002,
               altitude: 30.447654757346044
           },
           range: 334.8786935049066,
           tilt: 55.38819319004654,
           heading: 149.63867461295067,
       },
       point: { lat: 55.6804504, lng: 12.570279099999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/dk.svg'),
           scale: 1.0,
       },
   },
   ,
   {
       name: "Google Greece",
       details: "Fragkokklisias 6, Athina 151 25",
       camera: {
           center: {
               lat: 38.038634694028055,
               lng: 23.802924946201266,
               altitude: 196.45884670344995
           },
           range: 343.57226336076565,
           tilt: 54.97375927639567,
           heading: -33.26775344055724,
       },
       point: { lat: 38.038619, lng: 23.8031622, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Germany",
       details: "ABC-Straße 19, 20354 Hamburg",
       camera: {
           center: {
               lat: 53.55397683312404,
               lng: 9.986350507286808,
               altitude: 44.83610870143956
           },
           range: 375.3474077822466,
           tilt: 71.35078443829818,
           heading: -160.76930098951416,
       },
       point: { lat: 53.5540227, lng: 9.9863, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/de.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Ireland",
       details: "Gordon House, 4 Barrow St, Grand Canal Dock, Dublin 4, D04 V4X7",
       camera: {
           center: { lat: 53.339816899999995, lng: -6.2362644, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 53.339816899999995, lng: -6.2362644, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ie.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Italy",
       details: "Isola Building C, Via Federico Confalonieri, 4, 20124 Milano",
       camera: {
           center: {
               lat: 45.486361346538224,
               lng: 9.18995496294455,
               altitude: 138.55834058400072
           },
           range: 694.9398023590038,
           tilt: 57.822470255679114,
           heading: 84.10194883488619,
       },
       point: { lat: 45.4863064, lng: 9.1894762, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/it.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Lithuania",
       details: "Vilnius Tech Park, Antakalnis st. 17, 2nd building, LT-10312, Vilnius",
       camera: {
           center: {
               lat: 54.698040606567965,
               lng: 25.30965338542576,
               altitude: 111.80276944294413
           },
           range: 412.5808304977545,
           tilt: 43.50793332082195,
           heading: -29.181098269421028,
       },
       point: { lat: 54.6981204, lng: 25.3098617, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/at.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Netherlands",
       details: "Claude Debussylaan 34, 1082 MD Amsterdam",
       camera: {
           center: {
               lat: 52.33773837150874,
               lng: 4.871754560171063,
               altitude: 53.68063996154723
           },
           range: 473.1982259177312,
           tilt: 56.216523350388634,
           heading: 71.78252318033718,
       },
       point: { lat: 52.337801, lng: 4.872065999999999, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/nl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Norway",
       details: "Bryggegata 6, 0250 Oslo",
       camera: {
           center: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/no.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Poland",
       details: "Rondo Daszynskiego 2, 00-843 Warsaw",
       camera: {
           center: { lat: 52.22844380000001, lng: 20.9851819, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 52.22844380000001, lng: 20.9851819, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Portugal",
       details: "R. Duque de Palmela 37 Piso 4, 1250-097 Lisboa",
       camera: {
           center: {
               lat: 38.7240122810727,
               lng: -9.150628263172639,
               altitude: 55.299662291551044
           },
           range: 337.7474313328639,
           tilt: 56.79772652682846,
           heading: 176.0722118222208,
       },
       point: { lat: 38.723915999999996, lng: -9.150629, altitude: 35 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pt.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Romania",
       details: "Bulevardul Corneliu Coposu 6-8, București 030167",
       camera: {
           center: {
               lat: 44.43076650172983,
               lng: 26.109700164718586,
               altitude: 125.57895810814505
           },
           range: 364.25249956711923,
           tilt: 38.517539223834326,
           heading: -38.81294924429363,
       },
       point: { lat: 44.4309897, lng: 26.1095719, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ro.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Spain",
       details: "Torre Picasso, Pl. Pablo Ruiz Picasso, 1, Tetuán, 28020 Madrid",
       camera: {
           center: {
               lat: 40.450078762608875,
               lng: -3.6930085080020856,
               altitude: 753.6446342341894
           },
           range: 845.7279793010093,
           tilt: 46.752510050599746,
           heading: 4.718779524265234,
       },
       point: { lat: 40.450294199999995, lng: -3.6927915, altitude: 175 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/es.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Sweden",
       details: "Kungsbron 2, 111 22 Stockholm",
       camera: {
           center: {
               lat: 59.33313751316038,
               lng: 18.054618219238293,
               altitude: 16.728213706832868
           },
           range: 377.5210725830039,
           tilt: 63.59478230626709,
           heading: 98.53138488367703,
       },
       point: { lat: 59.3332093, lng: 18.0536386, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/se.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Switzerland",
       details: "Brandschenkestrasse 110, 8002 Zürich",
       camera: {
           center: {
               lat: 47.365411056285275,
               lng: 8.525063594405356,
               altitude: 419.2348376754488
           },
           range: 166.74918737631742,
           tilt: 59.31431457129067,
           heading: -32.620415961949206,
       },
       point: { lat: 47.365452, lng: 8.5249253, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ch.svg'),
           scale: 1.0,
       },
   }
]

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           officeLocations.forEach(office => {
               const marker = new Marker3DInteractiveElement({
                   position: office.point,
                   label: office.name,
                   altitudeMode: 'RELATIVE_TO_GROUND',
                   extruded: true,
               });

               marker.addEventListener('gmp-click', (event) => {
                   map3D.flyCameraTo({
                       endCamera: office.camera,
                       durationMillis: 2000,
                   });

                   map3D.addEventListener('gmp-animationend', () => {
                       map3D.flyCameraAround({
                           camera: office.camera,
                           durationMillis: 2000,
                           rounds: 1
                       });

                       map3D.addEventListener('gmp-animationend', () => {
                           map3D.flyCameraTo({
                               endCamera: europeCamera,
                               durationMillis: 2000,
                           });
                       }, { once: true });

                   }, { once: true });

                   event.stopPropagation();
               });

               const markerPin = new PinElement(office.pin);
               marker.append(markerPin);

               map3D.append(marker);
           });
           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

12. Następne kroki

W tym ćwiczeniu z programowania poznasz podstawy korzystania z modeli 3D w interfejsie Maps JavaScript API. Następnie spróbuj dodać do mapy niektóre z tych elementów:

  • Dodaj listę rozwijaną, aby umożliwić wybór biura.
  • Aby uzyskać więcej efektów, użyj innych opcji stylizacji znaczników.
  • Sprawdź dodatkowe biblioteki dostępne w Maps JavaScript API, które umożliwiają korzystanie z dodatkowych funkcji, takich jak wyświetlanie oceny każdego biura za pomocą identyfikatora miejsca.

Aby dowiedzieć się więcej o korzystaniu z Google Maps Platform i modeli 3D w internecie, zapoznaj się z tymi artykułami: