Membuat peta 3D pertama dengan SwiftUI

1. Sebelum memulai

Codelab ini mengajarkan cara membuat aplikasi peta 3D di SwiftUI menggunakan Maps 3D SDK for iOS.

Aplikasi yang menampilkan peta 3D San Francisco

Anda akan mempelajari:

  • Cara mengontrol kamera untuk melihat lokasi dan terbang di sekitar peta.
  • Cara menambahkan penanda dan model
  • Cara menggambar garis dan poligon
  • Cara menangani klik pengguna pada penanda Tempat.

Prasyarat

  • Project Konsol Google yang mengaktifkan penagihan
  • Kunci API, yang secara opsional dibatasi untuk Maps 3D SDK for iOS.
  • Pengetahuan dasar tentang pengembangan iOS dengan SwiftUI.

Yang akan Anda lakukan

  • Menyiapkan Xcode dan memasukkan SDK menggunakan Swift Package Manager
  • Mengonfigurasi aplikasi untuk menggunakan kunci API
  • Menambahkan Peta 3D dasar ke aplikasi Anda
  • Mengontrol kamera untuk terbang ke dan di sekitar lokasi tertentu
  • Menambahkan penanda, garis, poligon, dan model ke peta

Yang Anda butuhkan

  • Xcode 15 atau yang lebih baru.

2. Memulai persiapan

Untuk langkah pengaktifan berikut, Anda harus mengaktifkan Maps 3D SDK untuk iOS.

Menyiapkan Google Maps Platform

Jika Anda belum memiliki akun Google Cloud Platform dan project dengan penagihan diaktifkan, lihat panduan Memulai Google Maps Platform untuk membuat akun penagihan dan project.

  1. Di Cloud Console, klik menu drop-down project lalu pilih project yang ingin Anda gunakan untuk codelab ini.

  1. Aktifkan API dan SDK Google Maps Platform yang diperlukan untuk codelab ini di Google Cloud Marketplace. Untuk melakukannya, ikuti langkah-langkah dalam video ini atau dokumentasi ini.
  2. Buat kunci API di halaman Kredensial di Cloud Console. Anda dapat mengikuti langkah-langkah dalam video ini atau dokumentasi ini. Semua permintaan ke Google Maps Platform memerlukan kunci API.

Mengaktifkan Maps 3D SDK untuk iOS

Anda dapat menemukan Maps 3D SDK for iOS menggunakan link menu Google Maps Platform > API dan Layanan di konsol.

Klik Aktifkan untuk mengaktifkan API di project yang Anda pilih.

Mengaktifkan Maps 3D SDK di Konsol Google

3. Membuat aplikasi SwiftUI dasar

Catatan: Anda dapat menemukan kode solusi untuk setiap langkah di repo aplikasi contoh codelab di GitHub .

Buat aplikasi baru di Xcode.

Kode untuk langkah ini dapat ditemukan di folder GoogleMaps3DDemo di GitHub.

Buka Xcode dan buat aplikasi baru. Tentukan SwiftUI.

Panggil aplikasi Anda GoogleMaps3DDemo, dengan nama paket com.example.GoogleMaps3DDemo.

Mengimpor library GoogleMaps3D ke project Anda

Tambahkan SDK ke project Anda menggunakan Swift Package Manager.

Di project atau ruang kerja Xcode, buka File > Add Package Dependencies. Masukkan https://github.com/googlemaps/ios-maps-3d-sdk sebagai URL, tekan Enter untuk mengambil paket, lalu klik "Add Package".

Dari jendela Choose Package Products, pastikan GoogleMaps3D akan ditambahkan ke target utama yang Anda tetapkan. Setelah selesai, klik Tambahkan Paket.

Untuk memverifikasi penginstalan, buka panel Umum target Anda. Di Framework, Library, dan Konten Tersemat, Anda akan melihat paket yang diinstal. Anda juga dapat melihat bagian Dependensi Paket di Project Navigator untuk memverifikasi paket dan versinya.

Menambahkan kunci API

Anda dapat melakukan hard code pada kunci API ke dalam aplikasi, tetapi ini bukan praktik yang baik. Dengan menambahkan file konfigurasi, Anda dapat menjaga kerahasiaan Kunci API dan menghindari check-in ke kontrol sumber.

Membuat file konfigurasi baru di folder root project

Di Xcode, pastikan Anda melihat jendela penjelajah project. Klik kanan root project, lalu pilih "File Baru dari Template". Scroll hingga Anda melihat "File Setelan Konfigurasi". Pilih opsi ini, lalu klik "Berikutnya". Beri nama file Config.xcconfig dan pastikan folder root project dipilih. Klik "Buat" untuk membuat file.

Di editor, tambahkan baris ke file konfigurasi sebagai berikut: MAPS_API_KEY = YOUR_API_KEY

Ganti YOUR_API_KEY dengan kunci API Anda.

Tambahkan setelan ini ke Info.plist.

Untuk melakukannya, pilih root project dan klik tab "Info".

Tambahkan properti baru bernama MAPS_API_KEY dengan nilai $(MAPS_API_KEY).

Contoh kode aplikasi memiliki file Info.plist yang menentukan properti ini.

Menambahkan peta

Buka file bernama GoogleMaps3DDemoApp.swift. Ini adalah titik entri dan navigasi utama untuk aplikasi Anda.

Fungsi ini memanggil ContentView() yang menampilkan pesan Hello World.

Buka ContentView.swift di editor.

Tambahkan pernyataan import untuk GoogleMaps3D.

Hapus kode di dalam blok kode var body: some View {}. Deklarasikan Map() baru di dalam body.

Konfigurasi minimum yang Anda perlukan untuk melakukan inisialisasi Map adalah MapMode. Nilai ini memiliki dua kemungkinan nilai:

  • .hybrid - gambar satelit dengan jalan dan label, atau
  • .satellite - hanya citra satelit.

Pilih .hybrid.

File ContentView.swift Anda akan terlihat seperti ini.

import GoogleMaps3D
import SwiftUI

@main
struct ContentView: View {
    var body: some View {
      Map(mode: .hybrid)
    }
}

Tetapkan kunci API Anda.

Kunci API harus ditetapkan sebelum Peta diinisialisasi.

Anda dapat melakukannya dengan menetapkan Map.apiKey di pengendali peristiwa init() dari View apa pun yang berisi Peta. Anda juga dapat menetapkannya di GoogleMaps3DDemoApp.swift sebelum memanggil ContentView().

Di GoogleMaps3DDemoApp.swift, tetapkan Map.apiKey di pengendali peristiwa onAppear dari WindowGroup.

Mengambil kunci API dari file konfigurasi

Gunakan Bundle.main.infoDictionary untuk mengakses setelan MAPS_API_KEY yang Anda buat di file konfigurasi.

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
    }
  }
}

Build dan jalankan aplikasi Anda untuk memeriksa apakah aplikasi dimuat dengan benar. Anda akan melihat peta dunia.

Peta 3D yang menampilkan bumi

4. Menggunakan kamera untuk mengontrol tampilan peta

Membuat objek status kamera

Tampilan Peta 3D dikontrol oleh class Camera. Pada langkah ini, Anda akan mempelajari cara menentukan lokasi, ketinggian, arah, kemiringan, roll, dan rentang untuk menyesuaikan tampilan peta.

Tampilan peta 3D San Francisco

Membuat class Helpers untuk menyimpan setelan Kamera

Tambahkan file kosong baru bernama MapHelpers.swift. Dalam file baru, impor GoogleMaps3D, dan tambahkan ekstensi ke class Camera. Tambahkan variabel bernama sanFrancisco. Lakukan inisialisasi variabel ini sebagai objek Camera baru. Temukan kamera di latitude: 37.39, longitude: -122.08.

import GoogleMaps3D

extension Camera {
 public static var sanFrancisco: Camera = .init(latitude: 37.39, longitude: -122.08)
}

Menambahkan View baru ke Aplikasi

Buat file baru dengan nama CameraDemo.swift. Tambahkan garis besar dasar Tampilan SwiftUI baru ke file.

Tambahkan variabel @State bernama camera dari jenis Camera. Lakukan inisialisasi ke kamera sanFrancisco yang baru saja Anda tentukan.

Dengan menggunakan @State, Anda dapat mengikat Peta ke status kamera dan menggunakannya sebagai sumber tepercaya.

@State var camera: Camera = .sanFrancisco

Ubah panggilan fungsi Map() untuk menyertakan properti camera. Gunakan binding status kamera $camera untuk melakukan inisialisasi properti camera ke objek @State Kamera (.sanFrancisco).

import SwiftUI
import GoogleMaps3D

struct CameraDemo: View {
  @State var camera: Camera = .sanFrancisco
  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid)
    }
  }
}

Menambahkan UI navigasi dasar ke aplikasi

Tambahkan NavigationView ke titik entri aplikasi utama, GoogleMaps3DDemoApp.swift.

Tindakan ini akan memungkinkan pengguna melihat daftar demo dan mengklik setiap demo untuk membukanya.

Edit GoogleMaps3DDemoApp.swift untuk menambahkan NavigationView baru.

Tambahkan List yang berisi dua deklarasi NavigationLink.

NavigationLink pertama akan membuka ContentView() dengan deskripsi Text Basic Map.

NavigationLink kedua akan membuka CameraDemo().

...
      NavigationView {
        List {
          NavigationLink(destination: ContentView()) {
            Text("Basic Map")
          }
          NavigationLink(destination: CameraDemo()) {
            Text("Camera Demo")
          }
        }
      }
...

Menambahkan Pratinjau Xcode

Pratinjau adalah fitur Xcode yang canggih yang memungkinkan Anda melihat dan berinteraksi dengan aplikasi saat Anda membuat perubahan pada aplikasi.

Untuk menambahkan pratinjau, buka CameraDemo.swift. Tambahkan blok kode #Preview {} di luar struct.

#Preview {
 CameraDemo()
}

Buka atau muat ulang panel Pratinjau di Xcode. Peta akan menampilkan San Francisco.

Menyiapkan tampilan 3D kustom

Anda dapat menentukan parameter tambahan untuk mengontrol kamera:

  • heading: bearing dalam derajat dari utara untuk mengarahkan kamera.
  • tilt: sudut kemiringan dalam derajat, dengan 0 tepat di atas kepala dan 90 melihat secara horizontal.
  • roll: sudut roll di sekitar bidang vertikal kamera, dalam derajat
  • range: jarak kamera dalam meter dari lokasi lintang, bujur
  • altitude: tinggi kamera di atas permukaan laut

Jika Anda tidak memberikan parameter tambahan ini, nilai default akan digunakan.

Agar tampilan kamera menampilkan lebih banyak data 3D, tetapkan parameter awal untuk menampilkan tampilan miring yang lebih dekat.

Edit Camera yang Anda tentukan di MapHelpers.swift untuk menyertakan nilai untuk altitude, heading, tilt, roll, dan 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)

Build dan jalankan aplikasi untuk melihat dan menjelajahi tampilan 3D baru.

5. Animasi kamera dasar

Sejauh ini, Anda telah menggunakan kamera untuk menentukan satu lokasi dengan kemiringan, ketinggian, arah, dan rentang. Pada langkah ini, Anda akan mempelajari cara memindahkan tampilan kamera dengan menganimasikan properti ini dari status awal ke status baru.

Peta 3D Seattle

Terbang ke lokasi

Anda akan menggunakan metode Map.flyCameraTo() untuk menganimasikan kamera dari lokasi awal ke lokasi baru.

Metode flyCameraTo() menggunakan sejumlah parameter:

  • Camera yang mewakili lokasi akhir.
  • duration: Durasi animasi akan berjalan, dalam detik.
  • trigger: objek yang dapat diamati yang akan memicu animasi saat statusnya berubah.
  • completion: kode yang akan dieksekusi saat animasi selesai.

Menentukan lokasi tujuan penerbangan

Buka file MapHelpers.swift Anda.

Tentukan objek kamera baru untuk menampilkan Seattle.

public static var seattle: Camera = .init(latitude:
47.6210296,longitude: -122.3496903, heading: 149.0, tilt: 77.0, roll: 0.0, range: 4000)

Tambahkan tombol untuk memicu animasi.

Buka CameraDemo.swift Anda. Deklarasikan variabel Boolean baru di dalam struct.

Panggil animate dengan nilai awal false.

@State private var animate: Bool = false

Tambahkan Button di bawah VStack. Button akan memulai animasi peta.

Berikan beberapa Text yang sesuai ke Button seperti "Mulai Terbang".

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") {
      }
    }
  }
}

Dalam penutupan Tombol, tambahkan kode untuk mengalihkan status variabel animate.

      Button("Start Flying") {
        animate.toggle()
      }

Mulai animasi.

Tambahkan kode untuk memicu animasi flyCameraTo() saat status variabel animate berubah.

  var body: some View {
    VStack{
      Map(camera: $camera, mode: .hybrid)
        .flyCameraTo(
          .seattle,
          duration: 5,
          trigger: animate,
          completion: {  }
        )
      Button("Start Flying") {
        animate.toggle()
      }
    }
  }

Terbang di sekitar lokasi

Terbang di sekitar lokasi dapat dilakukan menggunakan metode Map.flyCameraAround(). Metode ini menggunakan beberapa parameter:

  • Camera yang menentukan lokasi dan tampilan.
  • duration dalam detik.
  • rounds: jumlah berapa kali animasi akan diulang.
  • trigger: objek yang dapat diamati yang akan memicu animasi.
  • callback: kode yang akan dieksekusi saat animasi berjalan.

Tentukan variabel @State baru bernama flyAround, dengan nilai awal false.

Setelah melakukannya, tambahkan panggilan ke flyCameraAround() segera setelah panggilan metode flyCameraTo().

Durasi terbang harus relatif lama sehingga tampilan berubah dengan lancar.

Pastikan untuk memicu animasi flyCameraAround() dengan mengubah status objek pemicu saat flyCameraTo() selesai.

Kode akan terlihat seperti ini.

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()
}

Lihat pratinjau atau jalankan aplikasi untuk melihat bahwa kamera terbang di sekitar tujuan setelah animasi flyCameraTo() selesai.

6. Menambahkan Penanda ke peta.

Pada langkah ini, Anda akan mempelajari cara menggambar pin penanda pada peta.

Anda akan membuat objek Marker dan menambahkannya ke peta. SDK akan menggunakan ikon default untuk penanda. Terakhir, Anda akan menyesuaikan ketinggian penanda dan properti lainnya untuk mengubah cara penanda ditampilkan.

Peta 3D yang menampilkan penanda peta

Buat Tampilan SwiftUI baru untuk demo Penanda Anda.

Tambahkan file Swift baru ke project Anda. Sebut sebagai MarkerDemo.swift.

Tambahkan garis batas Tampilan SwiftUI dan lakukan inisialisasi peta seperti yang Anda lakukan di CameraDemo.

import SwiftUI
import GoogleMaps3D

struct MarkerDemo: View {
  @State var camera: Camera = .sanFrancisco
  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid)
    }
  }
}

Melakukan inisialisasi objek Penanda

Deklarasikan variabel penanda baru bernama mapMarker. Di bagian atas blok kode struct di MarkerDemo.swift.

Tempatkan definisi di baris di bawah deklarasi camera Anda. Kode contoh ini melakukan inisialisasi semua properti yang tersedia.

  @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"
  )

Tambahkan Penanda ke peta Anda.

Untuk menggambar penanda, tambahkan ke penutupan yang dipanggil saat Peta dibuat.

struct MarkerDemo: View {
  @State var camera: Camera = .sanFrancisco
  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid) {
        mapMarker
      }
    }
  }
}

Tambahkan NavigationLink baru ke GoogleMaps3DDemoApp.swift dengan tujuan MarkerDemo() dan Text yang mendeskripsikannya sebagai "Demo Penanda".

...
      NavigationView {
        List {
          NavigationLink(destination: Map()) {
            Text("Basic Map")
          }
          NavigationLink(destination: CameraDemo()) {
            Text("Camera Demo")
          }
          NavigationLink(destination: MarkerDemo()) {
            Text("Marker Demo")
          }
        }
      }
...

Melihat pratinjau dan menjalankan Aplikasi

Muat ulang pratinjau atau jalankan aplikasi untuk melihat penanda.

Penanda yang Diekstrusi

Penanda dapat ditempatkan di atas tanah atau mesh 3D menggunakan altitude dan altitudeMode.

Salin deklarasi mapMarker di MarkerDemo.swift ke variabel Marker baru bernama extrudedMarker.

Tetapkan nilai yang bukan nol untuk altitude, 50 sudah cukup.

Ubah altitudeMode menjadi .relativeToMesh, dan tetapkan extruded ke true. Gunakan latitude dan longitude dari cuplikan kode di sini untuk menempatkan penanda di atas gedung pencakar langit.

  @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"
  )

Jalankan atau lihat pratinjau aplikasi lagi. Penanda akan muncul di atas bangunan 3D.

7. Tambahkan model ke peta Anda.

Model dapat ditambahkan dengan cara yang sama seperti Marker. Anda memerlukan file model yang dapat diakses melalui URL atau ditambahkan sebagai file lokal dalam project Anda. Untuk langkah ini, kita akan menggunakan file lokal yang dapat Anda download dari repositori GitHub untuk codelab ini.

Peta 3D San Francisco dengan model balon udara

Menambahkan file model ke project

Buat folder baru di project Xcode Anda bernama Models.

Download model dari repositori aplikasi contoh GitHub. Tambahkan ke project Anda dengan menariknya ke folder baru di tampilan project Xcode.

Pastikan Anda menetapkan target sebagai target utama untuk aplikasi Anda.

Periksa setelan Build Phases > Copy Bundle Resources untuk project Anda. File model harus ada dalam daftar resource yang disalin ke paket. Jika tidak ada, klik "+" untuk menambahkannya.

Tambahkan model ke aplikasi Anda.

Buat file SwiftUI baru bernama ModelDemo.swift.

Tambahkan pernyataan import untuk SwiftUI dan GoogleMaps3D seperti pada langkah sebelumnya.

Deklarasikan Map di dalam VStack di body Anda.

import SwiftUI
import GoogleMaps3D

struct ModelDemo: View {
  @State var camera: Camera = .sanFrancisco
  
  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid) {
        
      }
    }
  }
}

Dapatkan jalur model dari Paket Anda. Tambahkan kode untuk ini di luar struct.

private let fileUrl = Bundle.main.url(forResource: "balloon", withExtension: "glb")

Deklarasikan variabel untuk model Anda di dalam struct.

Berikan nilai default jika fileUrl tidak diberikan.

  @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. Gunakan model dengan Peta Anda.

Seperti menambahkan Marker, cukup berikan referensi ke Model Anda dalam deklarasi Map.

  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid) {
        balloonModel
      }
    }
  }

Melihat pratinjau dan menjalankan aplikasi

Tambahkan NavigationLink baru ke GoogleMaps3DDemoApp.swift, dengan tujuan ModelDemo() dan Text "Model Demo".

...
          NavigationLink(destination: ModelDemo()) {
            Text("Model Demo")
          }
...

Muat ulang pratinjau atau jalankan aplikasi Anda untuk melihat model.

8. Menggambar garis dan poligon di peta Anda.

Pada langkah ini, Anda akan mempelajari cara menambahkan garis dan bentuk poligon ke peta 3D.

Untuk mempermudah, Anda akan menentukan bentuk sebagai array objek LatLngAltitude. Dalam aplikasi sebenarnya, data mungkin dimuat dari file, panggilan API, atau database.

Peta 3D San Francisco yang menampilkan dua poligon dan polyline

Buat beberapa objek bentuk untuk mengelola data bentuk.

Tambahkan definisi Camera baru ke MapHelpers.swift yang melihat pusat kota San Francisco.

  public static var downtownSanFrancisco: Camera = .init(latitude: 37.7905, longitude: -122.3989, heading: 25, tilt: 71, range: 2500) 

Tambahkan file baru ke project Anda yang bernama ShapesDemo.swift. Tambahkan struct bernama ShapesDemo yang mengimplementasikan protokol View, dan tambahkan body ke dalamnya.

struct ShapesDemo: View {
  @State var camera: Camera = .downtownSanFrancisco

  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid) {

      }
    }
  }
}

Class yang akan Anda gunakan untuk mengelola data bentuk adalah Polyline dan Polygon. Buka ShapesDemo.swift dan tambahkan ke struct sebagai berikut.

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

Perhatikan parameter inisialisasi yang digunakan.

  • altitudeMode: .relativeToGround digunakan untuk mengekstrud poligon ke ketinggian tertentu di atas tanah.
  • altitudeMode: .clampToGround digunakan untuk membuat polyline mengikuti bentuk permukaan bumi.
  • gaya ditetapkan pada objek Polygon dengan membuat rantai panggilan metode ke styleOptions() setelah .init() dipanggil

Menambahkan bentuk ke Peta

Sama seperti pada langkah sebelumnya, bentuk dapat langsung ditambahkan ke penutupan Map. Buat Map di dalam VStack.

...
  var body: some View {
    VStack {
      Map(camera: $camera, mode: .hybrid) {
        polyline
        originPolygon
        destinationPolygon
      }
    }
  }
...

Melihat pratinjau dan menjalankan Aplikasi

Tambahkan kode Pratinjau dan periksa aplikasi Anda di panel Pratinjau di Xcode.

#Preview {
  ShapesDemo()
}

Untuk menjalankan aplikasi, tambahkan NavigationLink baru ke GoogleMaps3DDemoApp.swift yang membuka View demo baru.

...
          NavigationLink(destination: ShapesDemo()) {
            Text("Shapes Demo")
          }
...

Jalankan aplikasi dan jelajahi bentuk yang Anda tambahkan.

9. Menangani peristiwa ketuk pada penanda Tempat

Pada langkah ini, Anda akan mempelajari cara merespons ketukan pengguna pada penanda Tempat.

Peta yang menampilkan jendela pop-up dengan ID Tempat

Catatan: Untuk melihat penanda Tempat di peta, Anda harus menetapkan MapMode ke .hybrid.

Untuk menangani ketukan, Anda harus menerapkan metode Map.onPlaceTap.

Peristiwa onPlaceTap menyediakan objek PlaceTapInfo yang dapat Anda gunakan untuk mendapatkan ID Tempat penanda Place yang diketuk.

Anda dapat menggunakan ID Tempat untuk mencari detail lebih lanjut menggunakan Places SDK atau Places API.

Menambahkan Tampilan Swift baru

Tambahkan kode berikut ke file Swift baru bernama 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()
}

Melihat pratinjau dan menjalankan Aplikasi

Buka panel Pratinjau untuk melihat pratinjau aplikasi.

Untuk menjalankan aplikasi, tambahkan NavigationLink baru ke GoogleMaps3DDemoApp.swift.

...
          NavigationLink(destination: PlaceTapDemo()) {
            Text("Place Tap Demo")
          }
...

10. (Opsional) Lanjutkan

Animasi Kamera Lanjutan

Beberapa kasus penggunaan memerlukan animasi yang lancar di sepanjang urutan atau daftar lokasi atau status kamera, misalnya simulator penerbangan atau memutar ulang pendakian atau lari.

Pada langkah ini, Anda akan mempelajari cara memuat daftar lokasi dari file, dan menganimasikan setiap lokasi secara berurutan.

Tampilan peta 3D untuk mendekati Innsbruck

Memuat file yang berisi urutan lokasi.

Download flightpath.json dari repositori aplikasi contoh GitHub.

Buat folder baru di project Xcode Anda bernama JSON.

Tarik flightpath.json ke folder JSON di Xcode.

Tetapkan target sebagai target utama aplikasi Anda. Pastikan setelan Salin Resource Paket project Anda menyertakan file ini.

Buat dua file Swift baru di aplikasi Anda yang bernama FlightPathData.swift dan FlightDataLoader.swift.

Salin kode berikut ke aplikasi Anda. Kode ini membuat struct dan class yang membaca file lokal bernama "flighpath.json" dan mendekodenya sebagai JSON.

Struktur FlightPathData dan FlightPathLocation merepresentasikan struktur data dalam file JSON sebagai objek Swift.

Class FlightDataLoader membaca data dari file dan mendekodenya. Library ini mengadopsi protokol ObservableObject untuk memungkinkan aplikasi Anda mengamati perubahan pada datanya.

Data yang diuraikan diekspos melalui properti yang dipublikasikan.

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.")
        }
      }
    }
  }
}

Menganimasikan kamera di sepanjang setiap lokasi

Untuk menganimasikan kamera di antara urutan langkah, Anda akan menggunakan KeyframeAnimator.

Setiap Keyframe akan dibuat sebagai CubicKeyframe, sehingga perubahan status kamera dianimasikan dengan lancar.

Penggunaan flyCameraTo() akan menyebabkan tampilan "memantul" di antara setiap lokasi.

Pertama-tama, deklarasikan kamera bernama "innsbruck" di 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)

Sekarang, siapkan View baru dalam file baru bernama FlyAlongRoute.swift.

Impor SwiftUI dan GoogleMaps3D. Tambahkan Map dan Button di dalam VStack. Siapkan Button untuk mengalihkan status variabel animation Boolean.

Deklarasikan objek State untuk FlightDataLoader, yang akan memuat file JSON saat diinisialisasi.

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()
      }
    }
  }
}

Membuat Keyframe

Proses dasarnya adalah membuat fungsi yang menampilkan frame baru dalam urutan animasi. Setiap frame baru menentukan status kamera berikutnya yang akan dianimasikan oleh animator. Setelah fungsi ini dibuat, panggil dengan setiap lokasi dari file secara berurutan.

Tambahkan dua fungsi ke struct FlyAlongRoute Anda. Fungsi makeKeyFrame menampilkan CubicKeyframe dengan status Kamera. Fungsi makeCamera mengambil langkah dalam urutan data penerbangan dan menampilkan objek Camera yang mewakili langkah tersebut.

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

Menggabungkan animasi

Panggil keyframeAnimator setelah inisialisasi Map dan tetapkan nilai awal.

Anda memerlukan status kamera awal berdasarkan lokasi pertama di jalur penerbangan.

Animasi harus dipicu berdasarkan status perubahan variabel.

Konten keyframeAnimator harus berupa Peta.

Daftar keyframe yang sebenarnya dibuat dengan melakukan loop di setiap lokasi di jalur penerbangan.

   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])
              }
            })
          }
        )
   }

Melihat pratinjau dan menjalankan aplikasi Anda.

Buka panel Pratinjau untuk melihat pratinjau Tampilan Anda.

Tambahkan NavigationLink baru dengan tujuan FlightPathDemo() ke GoogleMaps3DDemoApp.swift dan jalankan aplikasi untuk mencobanya.

11. Selamat

Anda telah berhasil mem-build aplikasi yang

  • Menambahkan Peta 3D dasar ke aplikasi Anda.
  • Menambahkan penanda, garis, poligon, dan model ke peta Anda.
  • Mengimplementasikan kode untuk mengontrol kamera agar terbang melalui peta dan di sekitar lokasi tertentu.

Yang telah Anda pelajari

  • Cara menambahkan paket GoogleMaps3D ke Aplikasi SwiftUI Xcode.
  • Cara melakukan inisialisasi Peta 3D dengan Kunci API dan tampilan default.
  • Cara menambahkan penanda, model 3D, garis, dan poligon ke peta Anda.
  • Cara mengontrol kamera untuk menganimasikan gerakan ke lokasi lain.
  • Cara menangani peristiwa klik pada penanda Tempat.

Apa langkah selanjutnya?

  • Lihat panduan developer untuk mengetahui detail selengkapnya tentang hal yang dapat Anda lakukan dengan Maps 3D SDK for iOS.
  • Bantu kami membuat konten yang menurut Anda paling berguna dengan menjawab survei berikut:

Apa saja codelab lain yang ingin Anda lihat?

Visualisasi data pada peta Selengkapnya tentang cara menyesuaikan gaya peta saya Membuat interaksi 3D di peta