1. Zanim zaczniesz
Z tego ćwiczenia w Codelab dowiesz się, jak utworzyć aplikację z mapami 3D w SwiftUI za pomocą pakietu SDK Map 3D na iOS.
Dowiesz się:
- Jak sterować kamerą, aby wyświetlać lokalizacje i przemieszczać się po mapie.
- Dodawanie znaczników i modeli
- Jak rysować linie i wielokąty
- Jak obsługiwać kliknięcia przez użytkowników znaczników miejsc.
Wymagania wstępne
- projekt w Konsoli Google z włączonymi płatnościami;
- Klucz interfejsu API, opcjonalnie ograniczony do pakietu SDK Map 3D na iOS.
- podstawowa znajomość tworzenia aplikacji na iOS za pomocą SwiftUI;
Jakie zadania wykonasz
- Konfigurowanie Xcode i wprowadzanie pakietu SDK za pomocą menedżera pakietów Swift
- Konfigurowanie aplikacji do korzystania z klucza interfejsu API
- Dodawanie do aplikacji podstawowej mapy 3D
- Sterowanie kamerą w celu przemieszczania się do określonych miejsc i poruszania się wokół nich
- Dodawanie znaczników, linii, wielokątów i modeli do mapy
Czego potrzebujesz
- Xcode 15 lub nowsza wersja.
2. Konfiguracja
Aby wykonać następny krok, musisz włączyć pakiet SDK Map 3D na iOS.
Konfigurowanie Google Maps Platform
Jeśli nie masz jeszcze konta Google Cloud Platform i utworzonego projektu z włączonymi płatnościami, zapoznaj się z artykułem Pierwsze kroki z Google Maps Platform, aby utworzyć konto rozliczeniowe i projekt.
- W konsoli Google Cloud kliknij menu projektu i wybierz projekt, którego chcesz użyć w tym CodeLab.
- 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.
- 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.
Włączanie pakietu SDK Map 3D na iOS
Pakiet SDK Map 3D na iOS znajdziesz w konsoli, klikając w menu Google Maps Platform > Interfejsy API i usługi.
Kliknij Włącz, aby włączyć interfejs API w wybranym projekcie.
3. Tworzenie podstawowej aplikacji SwiftUI
Uwaga: kod rozwiązania dla każdego kroku znajdziesz w repozytorium przykładowej aplikacji na GitHubie .
Utwórz nową aplikację w Xcode.
Kod potrzebny do wykonania tego kroku znajdziesz w folderze GoogleMaps3DDemo na GitHubie.
Otwórz Xcode i utwórz nową aplikację. W oknie dialogowym „Framework” wybierz SwiftUI.
Nazwij aplikację GoogleMaps3DDemo
i nadaj jej nazwę pakietu com.example.GoogleMaps3DDemo
.
Importowanie biblioteki GoogleMaps3D do projektu
Dodaj pakiet SDK do projektu za pomocą menedżera pakietów Swift.
W projekcie lub obszarze roboczym Xcode wybierz Plik > Dodaj zależności pakietu. Wpisz https://github.com/googlemaps/ios-maps-3d-sdk jako adres URL, naciśnij klawisz Enter, aby zaimportować pakiet, i kliknij „Dodaj pakiet”.
W oknie Wybieranie produktów pakietu sprawdź, czy GoogleMaps3D
zostanie dodany do głównego celu. Gdy skończysz, kliknij Dodaj pakiet.
Aby sprawdzić instalację, otwórz panel Ogólne. W ramach opcji Ramy, Biblioteki i Zawartość osadzona powinny być widoczne zainstalowane pakiety. Możesz też wyświetlić sekcję Zależność pakietu w Nawigatorze projektu, aby sprawdzić pakiet i jego wersję.
Dodawanie klucza interfejsu API
Możesz zakodować klucz interfejsu API w aplikacji, ale nie jest to zalecana praktyka. Dodanie pliku konfiguracyjnego pozwala zachować w tajnych klucz interfejsu API i uniknąć jego sprawdzenia w systemie kontroli wersji.
Utwórz nowy plik konfiguracji w folderze głównym projektu.
W Xcode sprawdź, czy wyświetlasz okno Eksploratora projektu. Kliknij prawym przyciskiem myszy katalog główny projektu i wybierz „Nowy plik ze szablonu”. Przewiń, aż zobaczysz „Plik ustawień konfiguracji”. Wybierz tę opcję i kliknij „Dalej”. Nazwij plik Config.xcconfig
i upewnij się, że wybrany jest folder główny projektu. Aby utworzyć plik, kliknij „Utwórz”.
W edytorze dodaj do pliku konfiguracji wiersz w ten sposób: MAPS_API_KEY = YOUR_API_KEY
Zastąp YOUR_API_KEY
swoim kluczem API.
Dodaj to ustawienie do Info.plist
.
Aby to zrobić, wybierz katalog główny projektu i kliknij kartę „Informacje”.
Dodaj nową właściwość o nazwie MAPS_API_KEY
o wartości $(MAPS_API_KEY)
.
Przykładowy kod aplikacji zawiera plik Info.plist
, który określa tę właściwość.
Dodawanie mapy
Otwórz plik o nazwie GoogleMaps3DDemoApp.swift
. Jest to punkt wejścia i główna nawigacja w aplikacji.
Wywołuje on funkcję ContentView()
, która wyświetla komunikat „Hello World”.
Otwórz plik ContentView.swift
w edytorze.
Dodaj oświadczenie import
dla GoogleMaps3D
.
Usuń kod w bloku kodu var body: some View {}
. Zadeklaruj nową zmienną Map()
w bloku body
.
Minimalna konfiguracja potrzebna do zainicjowania Map
to MapMode
. Ma on 2 możliwe wartości:
.hybrid
– zdjęcia satelitarne z drożami i etykietami lub.satellite
– tylko zdjęcia satelitarne.
Wybierz firmę .hybrid
.
Plik ContentView.swift
powinien wyglądać tak.
import GoogleMaps3D
import SwiftUI
@main
struct ContentView: View {
var body: some View {
Map(mode: .hybrid)
}
}
Ustaw klucz interfejsu API.
Klucz API musi zostać ustawiony przed zainicjowaniem mapy.
Aby to zrobić, ustaw Map.apiKey
w obiekcie init()
w obiekcie View
, który zawiera mapę. Możesz też ustawić go w GoogleMaps3DDemoApp.swift
przed wywołaniem funkcji ContentView()
.
W GoogleMaps3DDemoApp.swift
ustaw wartość Map.apiKey
w module obsługi zdarzenia onAppear
w komponencie WindowGroup
.
Pobieranie klucza interfejsu API z pliku konfiguracyjnego
Użyj polecenia Bundle.main.infoDictionary
, aby uzyskać dostęp do ustawienia MAPS_API_KEY
utworzonego w pliku konfiguracji.
import GoogleMaps3D
import SwiftUI
@main
struct GoogleMaps3DDemoApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.onAppear {
guard let infoDictionary: [String: Any] = Bundle.main.infoDictionary else {
fatalError("Info.plist not found")
}
guard let apiKey: String = infoDictionary["MAPS_API_KEY"] as? String else {
fatalError("MAPS_API_KEY not set in Info.plist")
}
Map.apiKey = apiKey
}
}
}
Utwórz i uruchom aplikację, aby sprawdzić, czy wczytuje się prawidłowo. Powinna wyświetlić się mapa kuli ziemskiej.
4. Sterowanie widokiem mapy za pomocą aparatu
Tworzenie obiektu stanu aparatu
Wyświetlanie mapy 3D jest kontrolowane przez klasę Camera
. W tym kroku dowiesz się, jak określić lokalizację, wysokość, kierunek, pochylenie, obrót i zakres, aby dostosować widok mapy.
Utwórz klasę pomocniczą do przechowywania ustawień aparatu
Dodaj nowy pusty plik o nazwie MapHelpers.swift
. W nowym pliku zaimportuj GoogleMaps3D
i dodaj rozszerzenie do klasy Camera
. Dodaj zmienną o nazwie sanFrancisco
. Inicjuje tę zmienną jako nowy obiekt Camera
. Znajdź kamerę w miejscu latitude: 37.39, longitude: -122.08
.
import GoogleMaps3D
extension Camera {
public static var sanFrancisco: Camera = .init(latitude: 37.39, longitude: -122.08)
}
Dodawanie nowego widoku do aplikacji
Utwórz nowy plik o nazwie CameraDemo.swift
. Dodaj do pliku podstawowy zarys nowego widoku SwiftUI.
Dodaj zmienną @State
o nazwie camera
i typie Camera
. Zainicjuj go w zaraz zdefiniowanym aparacie sanFrancisco
.
Korzystając z funkcji @State
, możesz powiązać Mapę ze stanem kamery i używać jej jako źródła informacji.
@State var camera: Camera = .sanFrancisco
Zmień wywołanie funkcji Map()
, aby uwzględnić właściwość camera
. Użyj powiązania stanu kamery $camera
, aby zainicjować właściwość camera
w obiekcie Camera @State
(.sanFrancisco
).
import SwiftUI
import GoogleMaps3D
struct CameraDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
Dodawanie podstawowego interfejsu nawigacji do aplikacji
Dodaj NavigationView
do głównego punktu wejścia aplikacji, GoogleMaps3DDemoApp.swift
.
Dzięki temu użytkownicy zobaczą listę wersji demonstracyjnych i będą mogli kliknąć każdą z nich, aby ją otworzyć.
Kliknij Edytuj GoogleMaps3DDemoApp.swift
, aby dodać nowy NavigationView
.
Dodaj element List
zawierający 2 deklaracje NavigationLink
.
Pierwszy NavigationLink
powinien otwierać ContentView()
z Text
opisem Basic Map
.
Drugi NavigationLink
powinien otworzyć CameraDemo()
.
...
NavigationView {
List {
NavigationLink(destination: ContentView()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
}
}
...
Dodawanie podglądu Xcode
Podglądy to zaawansowana funkcja Xcode, która umożliwia wyświetlanie aplikacji i działanie w niej podczas wprowadzania zmian.
Aby dodać podgląd, otwórz CameraDemo.swift
. Dodaj blok kodu #Preview {}
poza elementem struct
.
#Preview {
CameraDemo()
}
Otwórz lub odśwież panel Podgląd w Xcode. Na mapie powinno być zaznaczone San Francisco.
Konfigurowanie widoków 3D niestandardowych
Możesz podać dodatkowe parametry, aby sterować kamerą:
heading
: kierunek w stopniach od północy, w którym ma być skierowana kamera.tilt
: kąt pochylenia w stopniach, gdzie 0 to bezpośrednio nad głową, a 90 to patrzący poziomo.roll
: kąt obrotu wokół osi pionowej kamery wyrażony w stopniachrange
: odległość w metrach od kamery do lokalizacji z szerokością i długością geograficznąaltitude
: wysokość aparatu nad poziomem morza
Jeśli nie podasz żadnego z tych dodatkowych parametrów, zostaną użyte wartości domyślne.
Aby widok z kamery pokazywał więcej danych 3D, ustaw początkowe parametry w taki sposób, aby wyświetlać bliższy, pochylony widok.
Zmień definicję typu Camera
w definicji MapHelpers.swift
, aby uwzględnić wartości altitude
, heading
, tilt
, roll
i range
.
public static var sanFrancisco: Camera = .init(
latitude: 37.7845812,
longitude: -122.3660241,
altitude: 585,
heading: 288.0,
tilt: 75.0,
roll: 0.0,
range: 100)
Zbuduj i uruchom aplikację, aby zobaczyć i przetestować nowy widok 3D.
5. Podstawowe animacje aparatu
Do tej pory używasz aparatu, aby określić pojedynczą lokalizację z pochyleniem, wysokością, kierunkiem i zakresem. W tym kroku dowiesz się, jak przesuwać widok kamery, animując te właściwości od stanu początkowego do nowego.
Poleć do lokalizacji
Aby animować kamerę od początkowej do nowej lokalizacji, użyjesz metody Map.flyCameraTo()
.
Metoda flyCameraTo()
przyjmuje kilka parametrów:
Camera
reprezentujący lokalizację końcową.duration
: czas trwania animacji w sekundach.trigger
: obserwowalny obiekt, który uruchamia animację po zmianie stanu.completion
: kod, który zostanie wykonany po zakończeniu animacji.
Określ miejsce docelowe
Otwórz plik MapHelpers.swift
.
Zdefiniuj nowy obiekt kamery, aby pokazać Seattle.
public static var seattle: Camera = .init(latitude:
47.6210296,longitude: -122.3496903, heading: 149.0, tilt: 77.0, roll: 0.0, range: 4000)
Dodaj przycisk, który uruchamia animację.
Otwórz CameraDemo.swift
. Zadeklaruj nową zmienną logiczną wewnątrz struct
.
Nazwij ją animate
i nadaj jej wartość początkową false
.
@State private var animate: Bool = false
Dodaj Button
poniżej VStack
. Button
inicjuje animację mapy.
Nadaj Button
odpowiednią Text
, np. „Start Flying” (Rozpocznij lot).
import SwiftUI
import GoogleMaps3D
struct CameraDemo: View {
@State var camera:Camera = .sanFrancisco
@State private var animate: Bool = false
var body: some View {
VStack{
Map(camera: $camera, mode: .hybrid)
Button("Start Flying") {
}
}
}
}
W bloku Button closure dodaj kod, aby przełączyć stan zmiennej animate
.
Button("Start Flying") {
animate.toggle()
}
Uruchom animację.
Dodaj kod, który uruchamia animację flyCameraTo()
, gdy zmienia się stan zmiennej animate
.
var body: some View {
VStack{
Map(camera: $camera, mode: .hybrid)
.flyCameraTo(
.seattle,
duration: 5,
trigger: animate,
completion: { }
)
Button("Start Flying") {
animate.toggle()
}
}
}
Oblot wokół lokalizacji
Oblot wokół lokalizacji można wykonać za pomocą metody Map.flyCameraAround()
. Ta metoda przyjmuje kilka parametrów:
Camera
określający lokalizację i widok.duration
w sekundach.rounds
: liczba powtórzeń animacji.trigger
: obserwowany obiekt, który uruchamia animację.callback
: kod, który zostanie wykonany podczas odtwarzania animacji.
Zdefiniuj nową zmienną @State
o nazwie flyAround
z wartością początkową false
.
Następnie dodaj wywołanie metody flyCameraAround()
bezpośrednio po wywołaniu metody flyCameraTo()
.
Czas trwania przelotu powinien być stosunkowo długi, aby widok zmieniał się płynnie.
Pamiętaj, aby po zakończeniu działania flyCameraTo()
wywołać animację flyCameraAround()
, zmieniając stan obiektu wyzwalacza.
Twój kod powinien wyglądać tak.
import SwiftUI
import GoogleMaps3D
struct CameraDemo: View {
@State var camera:Camera = .sanFrancisco
@State private var animate: Bool = false
@State private var flyAround: Bool = false
var body: some View {
VStack{
Map(camera: $camera, mode: .hybrid)
.flyCameraTo(
.seattle,
duration: 5,
trigger: animate,
completion: { flyAround = true }
)
.flyCameraAround(
.seattle,
duration: 15,
rounds: 0.5,
trigger: flyAround,
callback: { }
)
Button("Start Flying") {
animate.toggle()
}
}
}
}
#Preview {
CameraDemo()
}
Wyświetl podgląd lub uruchom aplikację, aby sprawdzić, czy po zakończeniu animacji flyCameraTo()
kamera przelatuje wokół miejsca docelowego.
6. Dodaj znacznik do mapy.
W tym kroku dowiesz się, jak narysować znacznik na mapie.
Utwórz obiekt Marker
i dodaj go do mapy. Pakiet SDK użyje domyślnej ikony znacznika. Na koniec dostosuj wysokość znacznika i inne właściwości, aby zmienić sposób jego wyświetlania.
Utwórz nowy widok SwiftUI na potrzeby demonstracji wskaźnika.
Dodaj do projektu nowy plik Swift. Nazwij ją MarkerDemo.swift
.
Dodaj zarys widoku SwiftUI i inicjuj mapę tak samo jak w funkcji CameraDemo
.
import SwiftUI
import GoogleMaps3D
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
Inicjowanie obiektu Marker
Zadeklaruj nową zmienną znacznika o nazwie mapMarker
. U góry bloku kodu struct
w MarkerDemo.swift
.
Umieść definicję w wierszu pod deklaracją camera
. Ten przykładowy kod inicjalizuje wszystkie dostępne właściwości.
@State var mapMarker: Marker = .init(
position: .init(
latitude: 37.8044862,
longitude: -122.4301493,
altitude: 0.0),
altitudeMode: .absolute,
collisionBehavior: .required,
extruded: false,
drawsWhenOccluded: true,
sizePreserved: true,
zIndex: 0,
label: "Test"
)
Dodaj znacznik do mapy.
Aby narysować znacznik, dodaj go do funkcji zamykającej wywoływanej podczas tworzenia mapy.
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
mapMarker
}
}
}
}
Dodaj nowy element NavigationLink
do elementu GoogleMaps3DDemoApp.swift
z miejscem docelowym MarkerDemo()
i elementem Text
o nazwie „Marker Demo”.
...
NavigationView {
List {
NavigationLink(destination: Map()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
NavigationLink(destination: MarkerDemo()) {
Text("Marker Demo")
}
}
}
...
Wyświetlanie podglądu i uruchamianie aplikacji
Odśwież podgląd lub uruchom aplikację, aby zobaczyć znacznik.
Znaczniki wytłaczane
Za pomocą właściwości altitude
i altitudeMode
możesz umieszczać znaczniki nad ziemią lub siatką 3D.
Skopiuj deklarację mapMarker
w bloku MarkerDemo.swift
do nowej zmiennej Marker
o nazwie extrudedMarker
.
Ustaw wartość niezerową dla parametru altitude
, np. 50.
Zmień wartość altitudeMode
na .relativeToMesh
, a wartość extruded
na true
. Aby umieścić znacznik na szczycie wieżowca, użyj w tym fragmencie kodu wartości latitude
i longitude
.
@State var extrudedMarker: Marker = .init(
position: .init(
latitude: 37.78980534,
longitude: -122.3969349,
altitude: 50.0),
altitudeMode: .relativeToMesh,
collisionBehavior: .required,
extruded: true,
drawsWhenOccluded: true,
sizePreserved: true,
zIndex: 0,
label: "Extruded"
)
Uruchom ponownie aplikację lub wyświetl jej podgląd. znacznik powinien pojawiać się na szczycie budynku 3D;
7. Dodaj model do mapy.
Pole Model
można dodawać w taki sam sposób jak pole Marker
. Potrzebujesz pliku modelu, do którego można uzyskać dostęp za pomocą adresu URL lub dodać go jako plik lokalny w projekcie. W tym kroku użyjemy pliku lokalnego, który możesz pobrać z repozytorium GitHub dla tego Codelab.
Dodawanie pliku modelu do projektu
Utwórz w projekcie Xcode nowy folder o nazwie Models
.
Pobierz model z repozytorium przykładowej aplikacji w GitHub. Dodaj go do projektu, przeciągając go do nowego folderu w widoku projektu Xcode.
Upewnij się, że ustawiony przez Ciebie obiekt jest głównym celem dla Twojej aplikacji.
Sprawdź ustawienia w sekcji Etapy kompilacji > Kopiowanie zasobów pakietu w projekcie. Plik modelu powinien znajdować się na liście zasobów skopiowanych do pakietu. Jeśli go nie ma, kliknij „+”, aby go dodać.
Dodaj model do aplikacji.
Utwórz nowy plik SwiftUI o nazwie ModelDemo.swift
.
Dodaj instrukcje import
dla zmiennych SwiftUI
i GoogleMaps3D
tak jak w poprzednich krokach.
Zadeklaruj Map
w ramach VStack
w Twoim body
.
import SwiftUI
import GoogleMaps3D
struct ModelDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
Pobierz ścieżkę modelu z pakietu. Dodaj kod dla tego poza struct
.
private let fileUrl = Bundle.main.url(forResource: "balloon", withExtension: "glb")
Zadeklaruj zmienną dla modelu wewnątrz struktury.
Podaj wartość domyślną na wypadek, gdyby nie podano wartości fileUrl
.
@State var balloonModel: Model = .init(
position: .init(
latitude: 37.791376,
longitude: -122.397571,
altitude: 300.0),
url: URL(fileURLWithPath: fileUrl?.relativePath ?? ""),
altitudeMode: .absolute,
scale: .init(x: 5, y: 5, z: 5),
orientation: .init(heading: 0, tilt: 0, roll: 0)
)
3. Użyj modelu w swojej Mapie.
Podobnie jak w przypadku dodawania Marker
, w deklaracji Map
podaj tylko odniesienie do Model
.
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
balloonModel
}
}
}
Wyświetlanie podglądu i uruchamianie aplikacji
Dodaj nowy element NavigationLink
do elementu GoogleMaps3DDemoApp.swift
, ustawiając jako miejsce docelowe element ModelDemo()
i element Text
„Model Demo”.
...
NavigationLink(destination: ModelDemo()) {
Text("Model Demo")
}
...
Aby zobaczyć model, odśwież podgląd lub uruchom aplikację.
8. Narysuj linię i wielokąt na mapie.
W tym kroku dowiesz się, jak dodawać linie i kształty wielokąta do mapy 3D.
Dla uproszczenia kształty zostaną zdefiniowane jako tablice obiektów LatLngAltitude
. W rzeczywistej aplikacji dane mogą być ładowane z pliku, wywołania interfejsu API lub bazy danych.
Utwórz obiekty kształtów, aby zarządzać danymi kształtów.
Dodaj do MapHelpers.swift
nową definicję Camera
, która obejmuje centrum San Francisco.
public static var downtownSanFrancisco: Camera = .init(latitude: 37.7905, longitude: -122.3989, heading: 25, tilt: 71, range: 2500)
Dodaj do projektu nowy plik o nazwie ShapesDemo.swift
. Dodaj struct
o nazwie ShapesDemo
, który implementuje protokół View
, i dodaj do niego body
.
struct ShapesDemo: View {
@State var camera: Camera = .downtownSanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
Klasy, których użyjesz do zarządzania danymi kształtów, to Polyline
i Polygon
. Otwórz ShapesDemo.swift
i dodaj je do struct
w ten sposób:
var polyline: Polyline = .init(coordinates: [
LatLngAltitude(latitude: 37.80515638571346, longitude: -122.4032569467164, altitude: 0),
LatLngAltitude(latitude: 37.80337073509504, longitude: -122.4012878349353, altitude: 0),
LatLngAltitude(latitude: 37.79925208843463, longitude: -122.3976697250461, altitude: 0),
LatLngAltitude(latitude: 37.7989102378512, longitude: -122.3983408725656, altitude: 0),
LatLngAltitude(latitude: 37.79887832784348, longitude: -122.3987094864192, altitude: 0),
LatLngAltitude(latitude: 37.79786443410338, longitude: -122.4066878788802, altitude: 0),
LatLngAltitude(latitude: 37.79549248916587, longitude: -122.4032992702785, altitude: 0),
LatLngAltitude(latitude: 37.78861484290265, longitude: -122.4019489189814, altitude: 0),
LatLngAltitude(latitude: 37.78618687561075, longitude: -122.398969592545, altitude: 0),
LatLngAltitude(latitude: 37.7892310309145, longitude: -122.3951458683092, altitude: 0),
LatLngAltitude(latitude: 37.7916358762409, longitude: -122.3981969390652, altitude: 0)
])
.stroke(GoogleMaps3D.Polyline.StrokeStyle(
strokeColor: UIColor(red: 0.09803921568627451, green: 0.403921568627451, blue: 0.8235294117647058, alpha: 1),
strokeWidth: 10.0,
outerColor: .white,
outerWidth: 0.2
))
.contour(GoogleMaps3D.Polyline.ContourStyle(isGeodesic: true))
var originPolygon: Polygon = .init(outerCoordinates: [
LatLngAltitude(latitude: 37.79165766856578, longitude: -122.3983762901255, altitude: 300),
LatLngAltitude(latitude: 37.7915324439261, longitude: -122.3982171091383, altitude: 300),
LatLngAltitude(latitude: 37.79166617650914, longitude: -122.3980478493319, altitude: 300),
LatLngAltitude(latitude: 37.79178986470217, longitude: -122.3982041104199, altitude: 300),
LatLngAltitude(latitude: 37.79165766856578, longitude: -122.3983762901255, altitude: 300 )
],
altitudeMode: .relativeToGround)
.style(GoogleMaps3D.Polygon.StyleOptions(fillColor:.green, extruded: true) )
var destinationPolygon: Polygon = .init(outerCoordinates: [
LatLngAltitude(latitude: 37.80515661739527, longitude: -122.4034307490334, altitude: 300),
LatLngAltitude(latitude: 37.80503794515428, longitude: -122.4032633416024, altitude: 300),
LatLngAltitude(latitude: 37.80517850164195, longitude: -122.4031056058006, altitude: 300),
LatLngAltitude(latitude: 37.80529346901115, longitude: -122.4032622466595, altitude: 300),
LatLngAltitude(latitude: 37.80515661739527, longitude: -122.4034307490334, altitude: 300 )
],
altitudeMode: .relativeToGround)
.style(GoogleMaps3D.Polygon.StyleOptions(fillColor:.red, extruded: true) )
Zwróć uwagę na użyte parametry inicjowania.
- Wartość
altitudeMode: .relativeToGround
służy do wytłaczania wielokątów do określonej wysokości nad ziemią. altitudeMode: .clampToGround
służy do dostosowania wielokąta do kształtu powierzchni Ziemi.- style są ustawiane w obiektach
Polygon
przez złączenie wywołania metodystyleOptions()
z wywołaniem metody.init()
.
Dodawanie kształtów do mapy
Podobnie jak w poprzednich krokach kształty można dodawać bezpośrednio do zamknięcia Map
. Utwórz Map
w VStack
.
...
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
polyline
originPolygon
destinationPolygon
}
}
}
...
Wyświetlanie podglądu i uruchamianie aplikacji
Dodaj kod podglądu i sprawdź aplikację w oknie Podgląd w Xcode.
#Preview {
ShapesDemo()
}
Aby uruchomić aplikację, dodaj do GoogleMaps3DDemoApp.swift
nowy element NavigationLink
, który otworzy nowy widok demonstracyjny.
...
NavigationLink(destination: ShapesDemo()) {
Text("Shapes Demo")
}
...
Uruchom aplikację i sprawdź dodane kształty.
9. Obsługa zdarzeń dotknięcia znaczników miejsca
Na tym etapie dowiesz się, jak reagować na kliknięcia przez użytkownika znaczników miejsc.
Uwaga: aby zobaczyć na mapie znaczniki miejsc, musisz ustawić wartość parametru MapMode
na .hybrid
.
Obsługa kliknięcia wymaga implementacji metody Map.onPlaceTap
.
Zdarzenie onPlaceTap
udostępnia obiekt PlaceTapInfo
, z którego można uzyskać identyfikator miejsca docelowego dotkniętego znacznika miejsca.
Za pomocą identyfikatora miejsca możesz uzyskać więcej informacji, korzystając z pakietu SDK Miejsc lub interfejsu API Miejsc.
Dodawanie nowego widoku Swift
Dodaj ten kod do nowego pliku Swift o nazwie PlaceTapDemo.swift
.
import GoogleMaps3D
import SwiftUI
struct PlaceTapDemo: View {
@State var camera: Camera = .sanFrancisco
@State var isPresented = false
@State var tapInfo: PlaceTapInfo?
var body: some View {
Map(camera: $camera, mode: .hybrid)
.onPlaceTap { tapInfo in
self.tapInfo = tapInfo
isPresented.toggle()
}
.alert(
"Place tapped - \(tapInfo?.placeId ?? "nil")",
isPresented: $isPresented,
actions: { Button("OK") {} }
)
}
}
#Preview {
PlaceTapDemo()
}
Wyświetlanie podglądu i uruchamianie aplikacji
Otwórz panel Podgląd, aby wyświetlić podgląd aplikacji.
Aby uruchomić aplikację, dodaj nowy element NavigationLink
do elementu GoogleMaps3DDemoApp.swift
.
...
NavigationLink(destination: PlaceTapDemo()) {
Text("Place Tap Demo")
}
...
10. (Opcjonalnie) Przejdź dalej
Zaawansowane animacje aparatu
Niektóre przypadki użycia wymagają płynnej animacji w ramach sekwencji lub listy lokalizacji bądź stanów kamery, np. w symulatorze lotu lub podczas odtwarzania wędrówki czy biegu.
W tym kroku dowiesz się, jak wczytać listę lokalizacji z pliku i animować każdą z nich po kolei.
Załaduj plik zawierający sekwencję lokalizacji.
Pobierz flightpath.json
z repozytorium przykładowej aplikacji na GitHubie.
Utwórz w projekcie Xcode nowy folder o nazwie JSON
.
Przeciągnij flightpath.json
do folderu JSON
w Xcode.
Ustaw go jako główny cel aplikacji. Sprawdź, czy ustawienia kopiowania zasobów pakietu w projekcie zawierają ten plik.
Utwórz w aplikacji 2 nowe pliki Swift o nazwach FlightPathData.swift
i FlightDataLoader.swift
.
Skopiuj do aplikacji ten kod. Tworzy on struktury i klasy, które odczytują lokalny plik o nazwie „flighpath.json” i dekodują go jako JSON.
Struktury FlightPathData
i FlightPathLocation
reprezentują strukturę danych w pliku JSON jako obiekty Swift.
Klasa FlightDataLoader
odczytuje dane z pliku i je zdekoduje. Używa on protokołu ObservableObject
, aby umożliwić aplikacji obserwowanie zmian w jej danych.
Przetworzone dane są udostępniane za pomocą opublikowanej usługi.
FlightPaths.swift
import GoogleMaps3D
struct FlightPathData: Decodable {
let flight: [FlightPathLocation]
}
struct FlightPathLocation: Decodable {
let timestamp: Int64
let latitude: Double
let longitude: Double
let altitude: Double
let bearing: Double
let speed: Double
}
FlightDataLoader.swift
import Foundation
public class FlightDataLoader : ObservableObject {
@Published var flightPathData: FlightPathData = FlightPathData(flight:[])
@Published var isLoaded: Bool = false
public init() {
load("flightpath.json")
}
public func load(_ path: String) {
if let url = Bundle.main.url(forResource: path, withExtension: nil){
if let data = try? Data(contentsOf: url){
let jsondecoder = JSONDecoder()
do{
let result = try jsondecoder.decode(FlightPathData.self, from: data)
flightPathData = result
isLoaded = true
}
catch {
print("Error trying to load or parse the JSON file.")
}
}
}
}
}
Animowanie kamery w każdej lokalizacji
Aby animować kamerę między sekwencjami kroków, użyj KeyframeAnimator
.
Każdy Keyframe
zostanie utworzony jako CubicKeyframe
, dzięki czemu zmiany stanu kamery będą płynnie animowane.
Użycie flyCameraTo()
spowoduje „przeskakiwanie” między poszczególnymi lokalizacjami.
Najpierw zadeklaruj kamerę o nazwie „innsbruck” w MapHelpers.swift
.
public static var innsbruck: Camera = .init(
latitude: 47.263,
longitude: 11.3704,
altitude: 640.08,
heading: 237,
tilt: 80.0,
roll: 0.0,
range: 200)
Teraz skonfiguruj nowy widok danych w nowym pliku o nazwie FlyAlongRoute.swift
.
Zaimportuj SwiftUI
i GoogleMaps3D
. Dodaj Map
i Button
wewnątrz VStack
. Ustaw zmienną Button
, aby przełączyć stan zmiennej logicznej animation
.
Zadeklaruj obiekt State
dla FlightDataLoader
, który wczyta plik JSON po jego zainicjowaniu.
import GoogleMaps3D
import SwiftUI
struct FlyAlongRoute: View {
@State private var camera: Camera = .innsbruck
@State private var flyToDuration: TimeInterval = 5
@State var animation: Bool = true
@StateObject var flightData: FlightDataLoader = FlightDataLoader()
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
Button("Fly Along Route"){
animation.toggle()
}
}
}
}
Tworzenie klatek kluczowych
Podstawowym procesem jest utworzenie funkcji, która zwraca nowy kadr w sekwencji animacji. Każdy nowy kadr określa następny stan kamery, który animator ma animować. Po utworzeniu tej funkcji wywołuj ją z poszczególnymi lokalizacjami z pliku w kolejności.
Dodaj do struktury FlyAlongRoute
2 funkcje. Funkcja makeKeyFrame
zwraca CubicKeyframe
z stanem aparatu. Funkcja makeCamera
wykonuje krok w sekwencji danych lotu i zwraca obiekt Camera
reprezentujący ten krok.
func makeKeyFrame(step: FlightPathLocation) -> CubicKeyframe<Camera> {
return CubicKeyframe(
makeCamera(step: step),
duration: flyToDuration
)
}
func makeCamera(step: FlightPathLocation) -> Camera {
return .init(
latitude: step.latitude,
longitude: step.longitude,
altitude: step.altitude,
heading: step.bearing,
tilt: 75,
roll: 0,
range: 200
)
}
Łączenie animacji
Wywołaj funkcję keyframeAnimator
po zainicjowaniu funkcji Map
i ustaw wartości początkowe.
Potrzebujesz początkowego stanu kamery na podstawie pierwszej lokalizacji na ścieżce lotu.
Animacja powinna być uruchamiana na podstawie zmiany stanu zmiennej.
Treści keyframeAnimator
powinny być mapą.
Rzeczywista lista klatek kluczowych jest generowana przez przechodzenie przez wszystkie lokalizacje na ścieżce lotu.
VStack {
Map(camera: $camera, mode: .hybrid)
.keyframeAnimator(
initialValue: makeCamera(step: flightData.flightPathData.flight[0]),
trigger: animation,
content: { view, value in
Map(camera: .constant(value), mode: .hybrid)
},
keyframes: { _ in
KeyframeTrack(content: {
for i in 1...flightData.flightPathData.flight.count-1 {
makeKeyFrame(step: flightData.flightPathData.flight[i])
}
})
}
)
}
Wyświetl podgląd aplikacji i uruchom ją.
Aby wyświetlić podgląd widoku, otwórz panel Podgląd.
Dodaj nowy NavigationLink
z miejscem docelowym FlightPathDemo()
do GoogleMaps3DDemoApp.swift
i uruchom aplikację, aby ją wypróbować.
11. Gratulacje
Udało Ci się utworzyć aplikację, która
- Dodaje do aplikacji podstawową mapę 3D.
- Dodaje do mapy znaczniki, linie, wielokąty i modele.
- Wdraża kod, który umożliwia sterowanie kamerą i przemieszczanie się po mapie oraz po określonych lokalizacjach.
Czego się nauczyłeś
- Jak dodać pakiet
GoogleMaps3D
do aplikacji SwiftUI w Xcode. - Jak zainicjować mapę 3D za pomocą klucza interfejsu API i widoku domyślnego
- Jak dodawać do mapy znaczniki, modele 3D, linie i wielokąty
- Jak sterować kamerą, aby animować ruch do innej lokalizacji.
- Jak obsługiwać zdarzenia kliknięcia na znacznikach miejsca.
Co dalej?
- Więcej informacji o tym, co możesz robić za pomocą pakietu SDK Map 3D na iOS, znajdziesz w przewodniku dla deweloperów.
- Pomóż nam tworzyć treści, które będą dla Ciebie najbardziej przydatne, wypełniając tę ankietę: