SwiftUI ile ilk 3D haritanızı oluşturma

1. Başlamadan önce

Bu codelab'de, iOS için Haritalar 3D SDK'sını kullanarak SwiftUI'de 3D harita uygulaması oluşturmayı öğreneceksiniz.

San Francisco'nun 3D haritasını gösteren uygulama

Öğrenecekleriniz:

  • Kamerayı kontrol ederek konumları görüntüleyebilir ve harita üzerinde uçabilirsiniz.
  • İşaretçi ve model ekleme
  • Çizgi ve poligon çizme
  • Kullanıcıların yer işaretçilerini tıklamasını işleme

Ön koşullar

  • Faturalandırmanın etkin olduğu bir Google Console projesi
  • İsteğe bağlı olarak iOS için Haritalar 3D SDK'sıyla kısıtlanmış bir API anahtarı.
  • SwiftUI ile iOS geliştirme hakkında temel düzeyde bilgi

Yapacaklarınız

  • Xcode'u ayarlama ve Swift Package Manager'ı kullanarak SDK'yı getirme
  • Uygulamanızı API anahtarı kullanacak şekilde yapılandırma
  • Uygulamanıza temel bir 3D harita ekleme
  • Belirli konumlara uçmak ve bu konumların etrafında uçmak için kamerayı kontrol etme
  • Haritanıza işaretçi, çizgi, poligon ve model ekleme

İhtiyacınız olanlar

  • Xcode 15 veya sonraki bir sürüm.

2. Hazırlanın

Aşağıdaki etkinleştirme adımı için iOS için Haritalar 3D SDK'sını etkinleştirmeniz gerekir.

Google Haritalar Platformu'nu ayarlama

Google Cloud Platform hesabınız ve faturalandırmanın etkin olduğu bir projeniz yoksa faturalandırma hesabı ve proje oluşturmak için lütfen Google Haritalar Platformu'nu kullanmaya başlama kılavuzunu inceleyin.

  1. Cloud Console'da proje açılır menüsünü tıklayın ve bu kod laboratuvarını kullanmak istediğiniz projeyi seçin.

  1. Google Cloud Marketplace'te bu kod laboratuvarı için gereken Google Haritalar Platformu API'lerini ve SDK'larını etkinleştirin. Bunun için bu videodaki veya bu dokümanlardaki adımları uygulayın.
  2. Cloud Console'un Kimlik Bilgileri sayfasında bir API anahtarı oluşturun. Bu videodaki veya bu dokümanlardaki adımları uygulayabilirsiniz. Google Haritalar Platformu'na yapılan tüm istekler için API anahtarı gerekir.

iOS için Haritalar 3D SDK'sını etkinleştirme

iOS için Haritalar 3D SDK'sını, konsoldaki Google Haritalar Platformu > API'ler ve Hizmetler menü bağlantısını kullanarak bulabilirsiniz.

Seçtiğiniz projede API'yi etkinleştirmek için Etkinleştir'i tıklayın.

Google Console'da Haritalar 3D SDK'sını etkinleştirme

3. Temel bir SwiftUI uygulaması oluşturma

Not: Her bir adıma ait çözüm kodunu GitHub'daki codelab örnek uygulama deposunda bulabilirsiniz .

Xcode'da yeni bir uygulama oluşturun.

Bu adımın kodunu GitHub'daki GoogleMaps3DDemo klasöründe bulabilirsiniz.

Xcode'u açıp yeni bir uygulama oluşturun. SwiftUI'yi belirtin.

Uygulamanızı GoogleMaps3DDemo olarak adlandırın ve com.example.GoogleMaps3DDemo paket adını kullanın.

GoogleMaps3D kitaplığını projenize aktarma

Swift Package Manager'ı kullanarak SDK'yı projenize ekleyin.

Xcode projenizde veya çalışma alanınızda Dosya > Paket Bağımlılıkları Ekle'ye gidin. URL olarak https://github.com/googlemaps/ios-maps-3d-sdk adresini girin, paketi almak için Enter tuşuna basın ve "Paket Ekle"yi tıklayın.

Paket Ürünlerini Seçin penceresinde, GoogleMaps3D'ün, belirttiğiniz ana hedefinize ekleneceğini doğrulayın. Bu işlem tamamlandıktan sonra Paket Ekle'yi tıklayın.

Yüklemenizin doğru olup olmadığını kontrol etmek için hedefinizin Genel bölmesine gidin. Çerçeveler, Kitaplıklar ve Yerleşik İçerik bölümünde yüklü paketleri görürsünüz. Paketi ve sürümünü doğrulamak için Proje Gezgini'nin Paket Bağımlılıkları bölümünü de görüntüleyebilirsiniz.

API anahtarınızı ekleme

API anahtarınızı uygulamaya sabit kod olarak ekleyebilirsiniz ancak bu iyi bir uygulama değildir. Yapılandırma dosyası eklemek, API anahtarınızı gizli tutmanıza olanak tanır ve kaynak denetimine eklenmesini önler.

Proje kök klasöründe yeni bir yapılandırma dosyası oluşturun

Xcode'da proje gezgini penceresini görüntülediğinizden emin olun. Proje kökünü sağ tıklayın ve "Şablondan Yeni Dosya"yı seçin. "Yapılandırma Ayarları Dosyası"nı görene kadar aşağı kaydırın. Bunu seçip "Sonraki"yi tıklayın. Dosyayı Config.xcconfig olarak adlandırın ve proje kök klasörünün seçildiğinden emin olun. Dosyayı oluşturmak için "Oluştur"u tıklayın.

Düzenleyicide, yapılandırma dosyasına aşağıdaki gibi bir satır ekleyin: MAPS_API_KEY = YOUR_API_KEY

YOUR_API_KEY yerine API anahtarınızı girin.

Bu ayarı Info.plist'e ekleyin.

Bunu yapmak için proje kökünü seçin ve "Bilgi" sekmesini tıklayın.

$(MAPS_API_KEY) değerine sahip MAPS_API_KEY adlı yeni bir mülk ekleyin.

Örnek uygulama kodunda bu özelliği belirten bir Info.plist dosyası vardır.

Harita ekleme

GoogleMaps3DDemoApp.swift adlı dosyayı açın. Bu, uygulamanızın giriş noktası ve ana gezinme menüsüdür.

Merhaba Dünya mesajı gösteren ContentView() işlevini çağırır.

ContentView.swift dosyasını düzenleyicide açın.

GoogleMaps3D için bir import ifadesi ekleyin.

var body: some View {} kod bloğundaki kodu silin. body içinde yeni bir Map() tanımlayın.

Bir Map'ü başlatmak için gereken minimum yapılandırma bir MapMode'tur. Bu özelliğin iki olası değeri vardır:

  • .hybrid: Yollar ve etiketler içeren uydu görüntüleri veya
  • .satellite: Yalnızca uydu görüntüleri.

.hybrid Farkını Tercih Edin.

ContentView.swift dosyanız aşağıdaki gibi görünmelidir.

import GoogleMaps3D
import SwiftUI

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

API anahtarınızı ayarlayın.

API anahtarı, harita başlatılmadan önce ayarlanmalıdır.

Bunu, harita içeren herhangi bir View öğesinin init() olay işleyicisinde Map.apiKey ayarlayarak yapabilirsiniz. Ayrıca ContentView()'u aramadan önce GoogleMaps3DDemoApp.swift'te de ayarlayabilirsiniz.

GoogleMaps3DDemoApp.swift içinde, WindowGroup öğesinin onAppear etkinlik işleyicisinde Map.apiKey değerini ayarlayın.

API anahtarınızı yapılandırma dosyasından getirme

Yapılandırma dosyanızda oluşturduğunuz MAPS_API_KEY ayarına erişmek için Bundle.main.infoDictionary kullanın.

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

Doğru şekilde yüklenip yüklenmediğini kontrol etmek için uygulamanızı derleyip çalıştırın. Dünya haritasını görürsünüz.

Dünyayı gösteren 3D harita

4. Harita görünümünü kontrol etmek için kamerayı kullanma

Kamera durumu nesnesi oluşturma

3D harita görünümleri Camera sınıfı tarafından kontrol edilir. Bu adımda, harita görünümünü özelleştirmek için konumu, irtifayı, yönü, eğimi, yuvarlanmayı ve menzili belirtmeyi öğreneceksiniz.

San Francisco'nun 3D harita görünümü

Kamera ayarlarını depolamak için bir Yardımcılar sınıfı oluşturma

MapHelpers.swift adlı yeni bir boş dosya ekleyin. Yeni dosyanızda GoogleMaps3D dosyasını içe aktarın ve Camera sınıfına bir uzantı ekleyin. sanFrancisco adlı bir değişken ekleyin. Bu değişkeni yeni bir Camera nesnesi olarak başlatın. Kamerayı latitude: 37.39, longitude: -122.08 konumunda bulun.

import GoogleMaps3D

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

Uygulamanıza yeni bir görünüm ekleme

CameraDemo.swift adlı yeni bir dosya oluşturun. Dosyaya yeni bir SwiftUI Görünümü'nün temel ana hatlarını ekleyin.

Camera türüne sahip camera adlı bir @State değişkeni ekleyin. Yeni tanımladığınız sanFrancisco kamerayla başlatın.

@State kullanarak haritayı kamera durumuna bağlayabilir ve doğru bilgi kaynağı olarak kullanabilirsiniz.

@State var camera: Camera = .sanFrancisco

Map() işlev çağrısını, camera özelliğini içerecek şekilde değiştirin. camera mülkünü kamera @State nesnenizde (.sanFrancisco) başlatmak için kamera durumu bağlama $camera özelliğini kullanın.

import SwiftUI
import GoogleMaps3D

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

Uygulamanıza temel gezinme kullanıcı arayüzü ekleme

Ana uygulama giriş noktasına (GoogleMaps3DDemoApp.swift) bir NavigationView ekleyin.

Bu sayede kullanıcılar demoların listesini görebilir ve her birini tıklayarak açabilir.

Yeni bir NavigationView eklemek için GoogleMaps3DDemoApp.swift'yi düzenleyin.

İki NavigationLink beyanı içeren bir List ekleyin.

İlk NavigationLink, ContentView()'u Text açıklamasıyla Basic Map açmalıdır.

İkinci NavigationLink, CameraDemo()'u açar.

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

Xcode önizlemesi ekleme

Önizlemeler, uygulamanızda değişiklik yaparken uygulamanızı görmenize ve uygulamanızla etkileşime geçmenize olanak tanıyan güçlü bir Xcode özelliğidir.

Önizleme eklemek için CameraDemo.swift'ü açın. struct dışında bir #Preview {} kod bloğu ekleyin.

#Preview {
 CameraDemo()
}

Xcode'da Önizleme bölmesini açın veya yenileyin. Haritada San Francisco gösterilmelidir.

Özel 3D görünümler oluşturma

Kamerayı kontrol etmek için ek parametreler belirtebilirsiniz:

  • heading: Kameranın kuzeyden hangi yöne bakacağını derece cinsinden gösteren yön.
  • tilt: Eğilme açısının derece cinsinden değeri. 0 doğrudan başınızın üzerinde, 90 ise yatay olarak baktığınız anlamına gelir.
  • roll: Kameranın dikey düzlemi etrafında derece cinsinden yan yatma açısı
  • range: Kameranın enlem, boylam konumuna olan mesafesi (metre cinsinden)
  • altitude: Kameranın deniz seviyesinden yüksekliği

Bu ek parametrelerden hiçbirini sağlamazsanız varsayılan değerler kullanılır.

Kamera görünümünde daha fazla 3D veri gösterilmesi için ilk parametreleri daha yakın ve eğik bir görünüm gösterecek şekilde ayarlayın.

MapHelpers.swift içinde tanımladığınız Camera öğesini altitude, heading, tilt, roll ve range değerlerini içerecek şekilde düzenleyin

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)

Yeni 3D görünümü görmek ve keşfetmek için uygulamayı derleyip çalıştırın.

5. Temel kamera animasyonları

Şimdiye kadar kamerayı kullanarak eğim, yükseklik, yön ve menzil içeren tek bir konum belirttiniz. Bu adımda, bu mülkleri ilk durumdan yeni bir duruma animasyonlu olarak taşıyarak kamera görüntüsünü nasıl taşıyacağınızı öğreneceksiniz.

Seattle'ın 3D haritası

Bir yere uçma

Kamerayı ilk konumdan yeni bir konuma animasyonlu olarak taşımak için Map.flyCameraTo() yöntemini kullanacaksınız.

flyCameraTo() yöntemi birkaç parametre alır:

  • Bitiş konumunu temsil eden bir Camera.
  • duration: Animasyonun saniye cinsinden süresi.
  • trigger: Durumu değiştiğinde animasyonu tetikleyecek gözlemlenebilir bir nesne.
  • completion: Animasyon tamamlandığında yürütülecek kod.

Uçuş yapılacak bir konum tanımlama

MapHelpers.swift dosyanızı açın.

Seattle'ı göstermek için yeni bir kamera nesnesi tanımlayın.

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

Animasyonu tetikleyecek bir düğme ekleyin.

CameraDemo.swift cihazınızı açın. struct içinde yeni bir Boole değişkeni tanımlayın.

animate olarak adlandırın ve ilk değeri false olarak ayarlayın.

@State private var animate: Bool = false

VStack altına bir Button ekleyin. Button, harita animasyonunu başlatır.

Button için "Uçmaya Başla" gibi uygun bir Text girin.

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

Düğme kapatma bölümünde, animate değişkeninin durumunu değiştirecek kod ekleyin.

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

Animasyonu başlatın.

animate değişkeninin durumu değiştiğinde flyCameraTo() animasyonunu tetikleyecek kodu ekleyin.

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

Bir konumun etrafında uçma

Bir konumun etrafında uçmak için Map.flyCameraAround() yöntemi kullanılabilir. Bu yöntem birkaç parametre alır:

  • konumu ve görünümü tanımlayan bir Camera.
  • duration saniye içinde.
  • rounds: Animasyonun tekrar sayısı.
  • trigger: Animasyonu tetikleyecek gözlemlenebilir bir nesne.
  • callback: Animasyon çalıştırıldığında çalışacak kod.

flyAround adlı, ilk değeri false olan yeni bir @State değişkeni tanımlayın.

Bunu yaptıktan sonra, flyCameraTo() yöntem çağrısından hemen sonra flyCameraAround() çağrısı ekleyin.

Görünümün sorunsuz bir şekilde değişebilmesi için çevreyi uçuş süresi nispeten uzun olmalıdır.

flyCameraTo() tamamlandığında tetikleyici nesnenin durumunu değiştirerek flyCameraAround() animasyonunu tetiklediğinizden emin olun.

Kodunuz aşağıdaki gibi görünmelidir.

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

flyCameraTo() animasyonu tamamlandıktan sonra kameranın hedefin etrafında uçtuğunu görmek için uygulamayı önizleyin veya çalıştırın.

6. Haritanıza bir işaretçi ekleyin.

Bu adımda, haritada nasıl işaretçi iğnesi çizeceğinizi öğreneceksiniz.

Bir Marker nesnesi oluşturup haritanıza eklersiniz. SDK, işaretçi için varsayılan bir simge kullanır. Son olarak, işaretçiyi nasıl gösterileceğini değiştirmek için işaretçi rakımı ve diğer özellikleri ayarlarsınız.

Harita işaretçisini gösteren 3D harita

İşaretçi denemeniz için yeni bir SwiftUI Görünümü oluşturun.

Projenize yeni bir Swift dosyası ekleyin. MarkerDemo.swift olarak adlandırın.

Bir SwiftUI Görünümü'nün ana hatlarını ekleyin ve haritayı CameraDemo'inizde yaptığınız gibi başlatın.

import SwiftUI
import GoogleMaps3D

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

Marker nesnesi başlatma

mapMarker adlı yeni bir işaretçi değişkeni tanımlayın. MarkerDemo.swift içindeki struct kod bloğunun üst kısmında.

Tanımı, camera beyanınızın altındaki satıra yerleştirin. Bu örnek kod, mevcut tüm mülkleri başlatır.

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

İşaretçiyi haritanıza ekleyin.

İşaretçiyi çizmek için harita oluşturulduğunda çağrılan bir kapatıcıya ekleyin.

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

GoogleMaps3DDemoApp.swift alanına MarkerDemo() hedefli ve Text "İşaretçi Demo" olarak tanımlanan yeni bir NavigationLink ekleyin.

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

Uygulamanızı önizleme ve çalıştırma

İşaretçiyi görmek için önizlemeyi yenileyin veya uygulamanızı çalıştırın.

Ekstrüde İşaretçiler

İşaretler, altitude ve altitudeMode kullanılarak zeminin veya 3D örgünün üzerine yerleştirilebilir.

MarkerDemo.swift içindeki mapMarker bildirimini extrudedMarker adlı yeni bir Marker değişkenine kopyalayın.

altitude için sıfır olmayan bir değer ayarlayın. 50 yeterlidir.

altitudeMode değerini .relativeToMesh olarak değiştirin ve extruded değerini true olarak ayarlayın. İşaretçiyi bir gökdelenin üzerine yerleştirmek için buradaki kod snippet'indeki latitude ve longitude değerlerini kullanın.

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

Uygulamayı tekrar çalıştırın veya önizleyin. İşaretçi, 3D bir binanın üzerinde görünür.

7. Haritanıza bir model ekleyin.

Model, Marker ile aynı şekilde eklenebilir. URL ile erişilebilen veya projenize yerel dosya olarak eklenebilen bir model dosyasına ihtiyacınız vardır. Bu adımda, bu kod laboratuvarının GitHub deposundan indirebileceğiniz yerel bir dosya kullanacağız.

Sıcak hava balonu modeli içeren San Francisco'nun 3D haritası

Projenize model dosyası ekleme

Xcode projenizde Models adlı yeni bir klasör oluşturun.

GitHub örnek uygulama deposundan modeli indirin. Xcode proje görünümündeki yeni klasöre sürükleyerek projenize ekleyin.

Hedefi, uygulamanızın ana hedefi olacak şekilde ayarladığınızdan emin olun.

Projenizin Derleme Aşamaları > Paket Kaynaklarını Kopyala ayarlarını kontrol edin. Model dosyası, pakete kopyalanan kaynaklar listesinde olmalıdır. Orada değilse eklemek için "+" simgesini tıklayın.

Modeli uygulamanıza ekleyin.

ModelDemo.swift adlı yeni bir SwiftUI dosyası oluşturun.

Önceki adımlarda olduğu gibi SwiftUI ve GoogleMaps3D için import ifadeleri ekleyin.

body dosyanızda VStack içinde bir Map tanımlayın.

import SwiftUI
import GoogleMaps3D

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

Paketinizden model yolunu alın. Bunun kodunu struct dışından ekleyin.

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

Yapı içinde modeliniz için bir değişken tanımlayın.

fileUrl sağlanmadığında varsayılan bir değer girin.

  @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. Modeli haritanızla kullanın.

Marker eklerken olduğu gibi, Map beyanında Model'unuzun referansını sağlamanız yeterlidir.

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

Uygulamanızı önizleme ve çalıştırma

GoogleMaps3DDemoApp.swift alanına, hedefi ModelDemo() ve Text "Model Demo" olan yeni bir NavigationLink ekleyin.

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

Modeli görmek için önizlemeyi yenileyin veya uygulamanızı çalıştırın.

8. Haritanızda bir çizgi ve poligon çizin.

Bu adımda, 3D haritanıza nasıl çizgi ve poligon şekli ekleyeceğinizi öğreneceksiniz.

Basitlik açısından şekilleri LatLngAltitude nesneleri dizileri olarak tanımlayacaksınız. Gerçek bir uygulamada veriler bir dosyadan, API çağrısından veya veritabanından yüklenebilir.

İki poligon ve bir çoklu çizginin gösterildiği San Francisco'nun 3D haritası

Şekil verilerini yönetmek için bazı şekil nesneleri oluşturun.

MapHelpers.swift alanına, San Francisco şehir merkezini kapsayan yeni bir Camera tanımı ekleyin.

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

Projenize ShapesDemo.swift adlı yeni bir dosya ekleyin. View protokolünü uygulayan ShapesDemo adlı bir struct ekleyin ve buna bir body ekleyin.

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

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

      }
    }
  }
}

Şekil verilerini yönetmek için kullanacağınız sınıflar Polyline ve Polygon'dır. ShapesDemo.swift'ü açın ve aşağıdaki gibi struct'a ekleyin.

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

Kullanılan ilk başlatma parametrelerine dikkat edin.

  • altitudeMode: .relativeToGround, poligonları yerden belirli bir yüksekliğe çıkarmak için kullanılır.
  • altitudeMode: .clampToGround, çoklu çizginin dünyanın yüzeyinin şeklini takip etmesini sağlamak için kullanılır.
  • .init() çağrıldıktan sonra styleOptions() için bir yöntem çağrısı zincirlenerek Polygon nesnelerinde stiller ayarlanır

Şekilleri haritaya ekleme

Önceki adımlarda olduğu gibi, şekiller doğrudan Map kapatma işlemine eklenebilir. Map öğenizi bir VStack içinde oluşturun.

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

Uygulamanızı önizleme ve çalıştırma

Xcode'daki Önizleme bölmesine önizleme kodu ekleyin ve uygulamanızı inceleyin.

#Preview {
  ShapesDemo()
}

Uygulamanızı çalıştırmak için GoogleMaps3DDemoApp.swift'a yeni bir NavigationLink ekleyin. Bu NavigationLink, yeni demo görünümünü açar.

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

Uygulamanızı çalıştırın ve eklediğiniz şekilleri keşfedin.

9. Yer işaretçilerinde dokunma etkinliklerini işleme

Bu adımda, kullanıcıların yer işaretlerine dokunmalarına nasıl yanıt vereceğinizi öğreneceksiniz.

Yer kimliği içeren bir pop-up pencere gösteren harita

Not: Yer işaretçilerini haritada görmek için MapMode.hybrid olarak ayarlamanız gerekir.

Dokunmayı işlemek için Map.onPlaceTap yönteminin uygulanması gerekir.

onPlaceTap etkinliği, dokunulan yer işaretçisinin yer kimliğini alabileceğiniz bir PlaceTapInfo nesnesi sağlar.

Yerler SDK'sı veya Yerler API'yi kullanarak daha fazla ayrıntıyı öğrenmek için yer kimliğini kullanabilirsiniz.

Yeni Swift Görünümü ekleme

Aşağıdaki kodu PlaceTapDemo.swift adlı yeni bir Swift dosyasına ekleyin.

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

Uygulamanızı önizleme ve çalıştırma

Uygulamayı önizlemek için Önizleme bölmesini açın.

Uygulamayı çalıştırmak için GoogleMaps3DDemoApp.swift alanına yeni bir NavigationLink ekleyin.

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

10. (İsteğe bağlı) Daha da ileri gitme

Gelişmiş kamera animasyonları

Bazı kullanım alanları, bir sıra veya konum ya da kamera durumu listesi boyunca sorunsuz bir şekilde animasyon yapılmasını gerektirir (ör. uçuş simülatörü veya bir yürüyüşü ya da koşuyu yeniden oynatma).

Bu adımda, bir dosyadan konum listesini nasıl yükleyeceğinizi ve her konumu sırayla nasıl canlandıracağınızı öğreneceksiniz.

Innsbruck'a yaklaşmanın 3D harita görünümü

Bir dizi konum içeren bir dosya yükleyin.

GitHub örnek uygulama deposundan flightpath.json dosyasını indirin.

Xcode projenizde JSON adlı yeni bir klasör oluşturun.

flightpath.json dosyasını Xcode'daki JSON klasörünüze sürükleyin.

Hedefi, uygulamanızın ana hedefi olacak şekilde ayarlayın. Projenizin Paket Kaynaklarını Kopyala ayarlarının bu dosyayı içerdiğinden emin olun.

Uygulamanızda FlightPathData.swift ve FlightDataLoader.swift adlı iki yeni Swift dosyası oluşturun.

Aşağıdaki kodu uygulamanıza kopyalayın. Bu kod, "flighpath.json" adlı yerel bir dosyayı okuyan ve JSON olarak kodunu çözen yapıları ve sınıfları oluşturur.

FlightPathData ve FlightPathLocation yapıları, JSON dosyasındaki veri yapısını Swift nesneleri olarak temsil eder.

FlightDataLoader sınıfı, dosyasındaki verileri okur ve kodlarını çözer. Uygulamanızın verilerindeki değişiklikleri gözlemlemesine izin vermek için ObservableObject protokolünü kullanır.

Ayrıştırılan veriler, yayınlanan bir mülk aracılığıyla gösterilir.

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

Kamerayı her konumda hareket ettirin

Kamerayı bir dizi adım arasında animasyonlu olarak hareket ettirmek için KeyframeAnimator kullanırsınız.

Her Keyframe, CubicKeyframe olarak oluşturulur. Böylece kamera durumundaki değişiklikler sorunsuz bir şekilde animasyonlu olarak gösterilir.

flyCameraTo() kullanılması, görünümün her konum arasında "zıplamasına" neden olur.

Öncelikle MapHelpers.swift içinde "innsbruck" adlı bir kamera tanımlayın.

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)

Ardından, FlyAlongRoute.swift adlı yeni bir dosyada yeni bir görünüm oluşturun.

SwiftUI ve GoogleMaps3D dosyalarını içe aktarın. Bir VStack içine bir Map ve bir Button ekleyin. Boole animation değişkeninin durumunu değiştirmek için Button'ü ayarlayın.

FlightDataLoader için bir State nesnesi tanımlayın. Bu nesne, başlatılırken JSON dosyasını yükler.

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

Animasyon karelerini oluşturma

Temel işlem, animasyon dizisinde yeni bir kare döndüren bir işlev oluşturmaktır. Her yeni kare, animatör tarafından animasyon oluşturulacak bir sonraki kamera durumunu tanımlar. Bu işlev oluşturulduktan sonra, dosyanın her bir konumunu sırayla kullanarak işlevi çağırın.

FlyAlongRoute yapınıza iki işlev ekleyin. makeKeyFrame işlevi, kamera durumu içeren bir CubicKeyframe döndürür. makeCamera işlevi, uçuş verileri dizisinde bir adım atar ve adımı temsil eden bir Camera nesnesi döndürür.

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

Animasyonu bir araya getirme

Map başlatıldıktan sonra keyframeAnimator işlevini çağırın ve ilk değerleri ayarlayın.

Uçuş yolundaki ilk konuma dayalı bir ilk kamera durumuna ihtiyacınız vardır.

Animasyon, değişkenin durumunun değişmesine göre tetiklenmelidir.

keyframeAnimator içeriği bir Harita olmalıdır.

Ana karelerin gerçek listesi, uçuş yolundaki her konumda döngü yapılarak oluşturulur.

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

Uygulamanızı önizleyin ve çalıştırın.

Görünümünüzü önizlemek için Önizleme bölmesini açın.

GoogleMaps3DDemoApp.swift'ye FlightPathDemo() hedefli yeni bir NavigationLink ekleyin ve denemek için uygulamayı çalıştırın.

11. Tebrikler

Aşağıdakileri başarıyla yapan bir uygulama oluşturdunuz:

  • Uygulamanıza temel bir 3D harita ekler.
  • Haritanıza işaretçi, çizgi, poligon ve model ekler.
  • Harita üzerinde ve belirli konumların etrafında uçmak için kamerayı kontrol edecek kod uygular.

Öğrendikleriniz

  • GoogleMaps3D paketini Xcode SwiftUI uygulamasına ekleme.
  • API anahtarı ve varsayılan görünüm içeren bir 3D haritayı başlatma.
  • Haritanıza işaretçi, 3D model, çizgi ve poligon ekleme.
  • Kamerayı kontrol ederek başka bir konuma hareketi animasyonlu olarak gösterme
  • Yer işaretçilerindeki tıklama etkinliklerini işleme

Sırada ne var?

  • iOS için Haritalar 3D SDK'sı ile neler yapabileceğiniz hakkında daha fazla bilgi için geliştirici kılavuzuna göz atın.
  • Aşağıdaki anketi yanıtlayarak en faydalı bulduğunuz içerikleri oluşturmamıza yardımcı olun:

Başka hangi Codelab'leri görmek istersiniz?

Haritalarda veri görselleştirme Haritalarımın stilini özelleştirme hakkında daha fazla bilgi Haritalarda 3D etkileşimler için bina oluşturma