1. قبل از شروع
این کد لبه به شما می آموزد که چگونه با استفاده از Maps 3D SDK برای iOS، یک برنامه نقشه های سه بعدی در SwiftUI ایجاد کنید.
یاد خواهید گرفت:
- نحوه کنترل دوربین برای مشاهده مکان ها و پرواز در اطراف نقشه.
- نحوه اضافه کردن نشانگرها و مدل ها
- نحوه رسم خطوط و چند ضلعی ها
- نحوه مدیریت کلیک های کاربر روی نشانگرهای مکان.
پیش نیازها
- یک پروژه Google Console با فعال کردن صورتحساب
- یک کلید API، که به صورت اختیاری محدود به Maps 3D SDK برای iOS است.
- دانش اولیه توسعه iOS با SwiftUI.
کاری که خواهی کرد
- Xcode را تنظیم کنید و SDK را با استفاده از Swift Package Manager وارد کنید
- برنامه خود را برای استفاده از کلید API پیکربندی کنید
- یک نقشه سه بعدی اولیه را به برنامه خود اضافه کنید
- دوربین را برای پرواز به مکان های خاص و اطراف آن کنترل کنید
- نشانگرها، خطوط، چند ضلعی ها و مدل ها را به نقشه خود اضافه کنید
آنچه شما نیاز دارید
- Xcode 15 یا بالاتر.
2. راه اندازی شوید
برای مرحله فعال سازی زیر، باید Maps 3D SDK را برای iOS فعال کنید.
پلتفرم نقشه های گوگل را راه اندازی کنید
اگر قبلاً یک حساب Google Cloud Platform و پروژهای با صورتحساب فعال ندارید، لطفاً راهنمای شروع به کار با Google Maps Platform را برای ایجاد یک حساب صورتحساب و یک پروژه ببینید.
- در Cloud Console ، روی منوی کشویی پروژه کلیک کنید و پروژه ای را که می خواهید برای این کد لبه استفاده کنید انتخاب کنید.
- APIها و SDKهای پلتفرم Google Maps مورد نیاز برای این لبه کد را در Google Cloud Marketplace فعال کنید. برای انجام این کار، مراحل این ویدیو یا این مستند را دنبال کنید.
- یک کلید API در صفحه Credentials در Cloud Console ایجاد کنید. می توانید مراحل این ویدئو یا این مستند را دنبال کنید. همه درخواستها به پلتفرم Google Maps به یک کلید API نیاز دارند.
Maps 3D SDK را برای iOS فعال کنید
میتوانید Maps 3D SDK برای iOS را با استفاده از پیوند منوی Google Maps Platform > APIs and Services در کنسول پیدا کنید.
روی Enable کلیک کنید تا API در پروژه انتخابی شما فعال شود.
3. یک برنامه اصلی SwiftUI ایجاد کنید
توجه: میتوانید کد راهحل را برای هر مرحله در مخزن نمونه برنامه Codelab در GitHub پیدا کنید.
یک برنامه جدید در Xcode ایجاد کنید.
کد این مرحله را میتوانید در پوشه GoogleMaps3DDemo در GitHub پیدا کنید.
Xcode را باز کنید و یک برنامه جدید ایجاد کنید. SwiftUI را مشخص کنید.
با برنامه GoogleMaps3DDemo
با نام بسته com.example.GoogleMaps3DDemo
تماس بگیرید.
کتابخانه GoogleMaps3D را به پروژه خود وارد کنید
با استفاده از Swift Package Manager، SDK را به پروژه خود اضافه کنید.
در پروژه یا فضای کاری Xcode خود، به File > Add Package Dependencies بروید. https://github.com/googlemaps/ios-maps-3d-sdk را به عنوان URL وارد کنید، Enter را فشار دهید تا بسته را وارد کنید و روی «افزودن بسته» کلیک کنید.
از پنجره انتخاب محصولات بسته، بررسی کنید که GoogleMaps3D
به هدف اصلی تعیین شده شما اضافه شود. پس از تکمیل، روی Add Package کلیک کنید.
برای تأیید نصب خود، به صفحه عمومی هدف خود بروید. در Frameworks، Libraries و Embedded Content، باید بسته های نصب شده را ببینید. همچنین میتوانید بخش Package Dependencies در Project Navigator را مشاهده کنید تا بسته و نسخه آن را تأیید کنید.
کلید API خود را اضافه کنید
میتوانید کلید API خود را در برنامه کدنویسی کنید، اما این تمرین خوبی نیست. افزودن یک فایل پیکربندی به شما امکان می دهد کلید API خود را مخفی نگه دارید و از بررسی آن در کنترل منبع اجتناب کنید.
یک فایل کانفیگ جدید در پوشه ریشه پروژه ایجاد کنید
در Xcode، مطمئن شوید که پنجره کاوشگر پروژه را مشاهده می کنید. روی ریشه پروژه کلیک راست کرده و "New File from Template" را انتخاب کنید. پیمایش کنید تا «فایل تنظیمات پیکربندی» را ببینید. این را انتخاب کنید و روی "بعدی" کلیک کنید. نام فایل را Config.xcconfig
و مطمئن شوید که پوشه ریشه پروژه انتخاب شده است. برای ایجاد فایل روی "ایجاد" کلیک کنید.
در ویرایشگر، یک خط به فایل پیکربندی به صورت زیر اضافه کنید: MAPS_API_KEY = YOUR_API_KEY
کلید API خود را جایگزین YOUR_API_KEY
کنید.
این تنظیم را به Info.plist
اضافه کنید.
برای انجام این کار، ریشه پروژه را انتخاب کرده و روی تب "Info" کلیک کنید.
یک ویژگی جدید به نام MAPS_API_KEY
با مقدار $(MAPS_API_KEY)
اضافه کنید.
کد برنامه نمونه دارای یک فایل Info.plist
است که این ویژگی را مشخص می کند.
یک نقشه اضافه کنید
فایلی به نام GoogleMaps3DDemoApp.swift
را باز کنید. این نقطه ورودی و مسیریابی اصلی برنامه شما است.
ContentView()
را فراخوانی می کند که پیام Hello World را نشان می دهد.
ContentView.swift
را در ویرایشگر باز کنید.
یک بیانیه import
برای GoogleMaps3D
اضافه کنید.
کد داخل var body: some View {}
. یک Map()
جدید در داخل body
اعلام کنید.
حداقل پیکربندی که برای مقداردهی اولیه Map
نیاز دارید، MapMode
است. این دو مقدار ممکن دارد:
-
.hybrid
- تصاویر ماهواره ای با جاده ها و برچسب ها، یا -
.satellite
- فقط تصاویر ماهواره ای.
.hybrid
را انتخاب کنید.
فایل ContentView.swift
شما باید شبیه این باشد.
import GoogleMaps3D
import SwiftUI
@main
struct ContentView: View {
var body: some View {
Map(mode: .hybrid)
}
}
کلید API خود را تنظیم کنید.
کلید API باید قبل از مقداردهی اولیه نقشه تنظیم شود.
می توانید این کار را با تنظیم Map.apiKey
در کنترل کننده رویداد init()
هر View
که حاوی نقشه است انجام دهید. همچنین می توانید قبل از فراخوانی ContentView()
آن را در GoogleMaps3DDemoApp.swift
تنظیم کنید.
در GoogleMaps3DDemoApp.swift
، Map.apiKey
در کنترل کننده رویداد onAppear
WindowGroup
تنظیم کنید.
کلید API خود را از فایل پیکربندی واکشی کنید
از Bundle.main.infoDictionary
برای دسترسی به تنظیمات MAPS_API_KEY
که در فایل پیکربندی خود ایجاد کرده اید، استفاده کنید.
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
}
}
}
برنامه خود را بسازید و اجرا کنید تا بررسی کنید که درست بارگیری شود. شما باید نقشه ای از کره زمین را ببینید.
4. از دوربین برای کنترل نمای نقشه استفاده کنید
یک شی وضعیت دوربین ایجاد کنید
نماهای نقشه سه بعدی توسط کلاس Camera
کنترل می شود. در این مرحله یاد خواهید گرفت که مکان، ارتفاع، عنوان، شیب، رول و محدوده را برای سفارشی کردن نمای نقشه مشخص کنید.
یک کلاس Helpers برای ذخیره تنظیمات دوربین ایجاد کنید
یک فایل خالی جدید به نام MapHelpers.swift
اضافه کنید. در فایل جدید خود، GoogleMaps3D
را وارد کنید و یک برنامه افزودنی به کلاس Camera
اضافه کنید. یک متغیر به نام sanFrancisco
اضافه کنید. این متغیر را به عنوان یک شیء Camera
جدید راه اندازی کنید. دوربین را در latitude: 37.39, longitude: -122.08
قرار دهید.
import GoogleMaps3D
extension Camera {
public static var sanFrancisco: Camera = .init(latitude: 37.39, longitude: -122.08)
}
یک نمای جدید به برنامه خود اضافه کنید
یک فایل جدید به نام CameraDemo.swift
ایجاد کنید. طرح کلی یک نمای SwiftUI جدید را به فایل اضافه کنید.
یک متغیر @State
به نام camera
از نوع Camera
اضافه کنید. آن را در دوربین sanFrancisco
که به تازگی تعریف کردید، مقداردهی اولیه کنید.
استفاده از @State
به شما امکان می دهد نقشه را به وضعیت دوربین متصل کنید و از آن به عنوان منبع حقیقت استفاده کنید.
@State var camera: Camera = .sanFrancisco
فراخوانی تابع Map()
را تغییر دهید تا دارای ویژگی camera
باشد. برای مقداردهی اولیه ویژگی camera
به شئ Camera @State
( .sanFrancisco
) از حالت camera binding $camera
استفاده کنید.
import SwiftUI
import GoogleMaps3D
struct CameraDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
رابط کاربری اصلی ناوبری را به برنامه خود اضافه کنید
یک NavigationView
به نقطه ورودی اصلی برنامه، GoogleMaps3DDemoApp.swift
اضافه کنید.
این به کاربران امکان می دهد لیستی از دموها را ببینند و روی هر کدام کلیک کنند تا باز شود.
برای افزودن NavigationView
جدید، GoogleMaps3DDemoApp.swift
را ویرایش کنید.
یک List
حاوی دو اعلان NavigationLink
اضافه کنید.
اولین NavigationLink
باید ContentView()
با توضیحات Text
Basic Map
باز کند.
دومین NavigationLink
باید CameraDemo()
باز کند.
...
NavigationView {
List {
NavigationLink(destination: ContentView()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
}
}
...
یک پیش نمایش Xcode اضافه کنید
پیش نمایش ها یک ویژگی قدرتمند Xcode است که به شما امکان می دهد برنامه خود را هنگام ایجاد تغییرات در آن ببینید و با آن تعامل داشته باشید.
برای افزودن پیشنمایش، CameraDemo.swift
را باز کنید. یک بلوک کد #Preview {}
خارج از struct
اضافه کنید.
#Preview {
CameraDemo()
}
پنجره پیش نمایش را در Xcode باز یا تازه کنید. نقشه باید سانفرانسیسکو را نشان دهد.
نماهای سه بعدی سفارشی را تنظیم کنید
می توانید پارامترهای اضافی را برای کنترل دوربین مشخص کنید:
-
heading
: یاتاقان بر حسب درجه از شمال به سمت دوربین. -
tilt
: زاویه شیب بر حسب درجه، که 0 مستقیماً بالای سر و 90 به صورت افقی است. -
roll
: زاویه چرخش در اطراف صفحه عمودی دوربین، بر حسب درجه -
range
: فاصله دوربین بر حسب متر از موقعیت جغرافیایی، طول جغرافیایی -
altitude
: ارتفاع دوربین از سطح دریا
اگر هیچ یک از این پارامترهای اضافی را ارائه نکنید، از مقادیر پیش فرض استفاده می شود.
برای اینکه نمای دوربین دادههای سه بعدی بیشتری را نشان دهد، پارامترهای اولیه را طوری تنظیم کنید که نمای نزدیکتر و کجتری را نشان دهد.
Camera
که در MapHelpers.swift
تعریف کردهاید ویرایش کنید تا مقادیر altitude
، heading
، tilt
، roll
و 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)
برنامه را بسازید و اجرا کنید تا نمای سه بعدی جدید را ببینید و کاوش کنید.
5. انیمیشن های دوربین اصلی
تاکنون از دوربین برای تعیین یک مکان با شیب، ارتفاع، سمت و محدوده استفاده کردهاید. در این مرحله یاد می گیرید که چگونه نمای دوربین را با متحرک سازی این ویژگی ها از حالت اولیه به حالت جدید منتقل کنید.
به یک مکان پرواز کنید
شما از متد Map.flyCameraTo()
برای متحرک سازی دوربین از محل اولیه به مکان جدید استفاده خواهید کرد.
متد flyCameraTo()
تعدادی پارامتر را می گیرد:
-
Camera
که مکان پایانی را نشان می دهد. -
duration
: مدت زمان اجرای انیمیشن، در چند ثانیه. -
trigger
: یک شی قابل مشاهده که انیمیشن را با تغییر حالت آن فعال می کند. -
completion
: کدی که پس از تکمیل انیمیشن اجرا می شود.
مکانی را برای پرواز تعیین کنید
فایل MapHelpers.swift
خود را باز کنید.
یک شی دوربین جدید برای نشان دادن سیاتل تعریف کنید.
public static var seattle: Camera = .init(latitude:
47.6210296,longitude: -122.3496903, heading: 149.0, tilt: 77.0, roll: 0.0, range: 4000)
یک دکمه برای فعال کردن انیمیشن اضافه کنید.
CameraDemo.swift
خود را باز کنید. یک متغیر بولی جدید در داخل struct
اعلان کنید.
آن را animate
با مقدار اولیه false
بنامید.
@State private var animate: Bool = false
یک Button
زیر VStack
اضافه کنید. Button
انیمیشن نقشه را آغاز می کند.
به Button
Text
مناسبی مانند "شروع پرواز" بدهید.
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") {
}
}
}
}
در بسته شدن دکمه، کدی را برای تغییر وضعیت متغیر animate
اضافه کنید.
Button("Start Flying") {
animate.toggle()
}
انیمیشن را شروع کنید.
هنگامی که وضعیت متغیر animate
تغییر می کند، کدی را برای فعال کردن انیمیشن flyCameraTo()
اضافه کنید.
var body: some View {
VStack{
Map(camera: $camera, mode: .hybrid)
.flyCameraTo(
.seattle,
duration: 5,
trigger: animate,
completion: { }
)
Button("Start Flying") {
animate.toggle()
}
}
}
در اطراف یک مکان پرواز کنید
با استفاده از روش Map.flyCameraAround()
می توان به پرواز در اطراف یک مکان دست یافت. این روش چندین پارامتر دارد:
- یک
Camera
که مکان و نمای را مشخص می کند. -
duration
در ثانیه -
rounds
: تعداد دفعات تکرار انیمیشن. -
trigger
: یک شی قابل مشاهده که انیمیشن را فعال می کند. -
callback
: کدی که با اجرای انیمیشن اجرا می شود.
یک متغیر @State
به نام flyAround
با مقدار اولیه false
تعریف کنید.
هنگامی که این کار را انجام دادید، بلافاصله پس از فراخوانی متد flyCameraTo()
flyCameraAround()
اضافه کنید.
مدت زمان پرواز در اطراف باید نسبتا طولانی باشد تا دید به آرامی تغییر کند.
مطمئن شوید که انیمیشن flyCameraAround()
را با تغییر وضعیت شی ماشه پس از تکمیل flyCameraTo()
فعال کنید.
کد شما باید شبیه این باشد.
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()
در اطراف مقصد پرواز می کند.
6. یک نشانگر به نقشه خود اضافه کنید.
در این مرحله یاد خواهید گرفت که چگونه یک پین نشانگر روی نقشه بکشید.
شما یک شی Marker
ایجاد می کنید و آن را به نقشه خود اضافه می کنید. SDK از یک نماد پیشفرض برای نشانگر استفاده میکند. در نهایت ارتفاع نشانگر و سایر خصوصیات را برای تغییر نحوه نمایش آن تنظیم خواهید کرد.
یک نمای SwiftUI جدید برای نمایشگر نشانگر خود ایجاد کنید.
یک فایل Swift جدید به پروژه خود اضافه کنید. نام آن را MarkerDemo.swift
بگذارید.
طرح کلی یک نمای SwiftUI را اضافه کنید و نقشه را همانطور که در CameraDemo
انجام دادید مقداردهی اولیه کنید.
import SwiftUI
import GoogleMaps3D
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
یک شی نشانگر را مقدار دهی اولیه کنید
یک متغیر نشانگر جدید به نام mapMarker
اعلام کنید. در بالای بلوک کد struct
در MarkerDemo.swift
.
تعریف را در خط زیر اعلامیه camera
خود قرار دهید. این کد نمونه تمام ویژگی های موجود را مقداردهی اولیه می کند.
@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"
)
نشانگر را به نقشه خود اضافه کنید.
برای ترسیم نشانگر، آن را به یک بسته که هنگام ایجاد نقشه نامیده می شود، اضافه کنید.
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
mapMarker
}
}
}
}
یک NavigationLink
جدید به GoogleMaps3DDemoApp.swift
با مقصد MarkerDemo()
و Text
که آن را به عنوان "Marker Demo" توصیف می کند، اضافه کنید.
...
NavigationView {
List {
NavigationLink(destination: Map()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
NavigationLink(destination: MarkerDemo()) {
Text("Marker Demo")
}
}
}
...
برنامه خود را پیش نمایش و اجرا کنید
پیش نمایش را بازخوانی کنید یا برنامه خود را اجرا کنید تا نشانگر را ببینید.
نشانگرهای اکسترود شده
نشانگرها را می توان با استفاده از altitude
و altitudeMode
در بالای سطح زمین یا شبکه سه بعدی قرار داد.
اعلان mapMarker
را در MarkerDemo.swift
در یک متغیر Marker
جدید به نام extrudedMarker
کپی کنید.
یک مقدار غیر صفر برای altitude
تنظیم کنید، 50 کافی است.
altitudeMode
به .relativeToMesh
تغییر دهید و extruded
روی true
قرار دهید. از latitude
و 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"
)
دوباره برنامه را اجرا یا پیش نمایش کنید. نشانگر باید در بالای یک ساختمان سه بعدی ظاهر شود.
7. یک مدل به نقشه خود اضافه کنید.
یک Model
می توان به همان روشی که یک Marker
اضافه کرد. شما به یک فایل مدل نیاز دارید که می توان از طریق URL به آن دسترسی پیدا کرد یا به عنوان یک فایل محلی در پروژه خود اضافه کرد. برای این مرحله از یک فایل محلی استفاده می کنیم که می توانید آن را از مخزن GitHub برای این کد لبه دانلود کنید.
یک فایل مدل به پروژه خود اضافه کنید
یک پوشه جدید در پروژه Xcode خود به نام Models
ایجاد کنید.
مدل را از مخزن نمونه برنامه GitHub دانلود کنید. با کشیدن آن به پوشه جدید در نمای پروژه Xcode، آن را به پروژه خود اضافه کنید.
مطمئن شوید که هدف را هدف اصلی برنامه خود قرار داده اید.
تنظیمات Build Phases > Copy Bundle Resources را برای پروژه خود بررسی کنید. فایل مدل باید در لیست منابع کپی شده در بسته باشد. اگر آنجا نیست روی "+" کلیک کنید تا آن را اضافه کنید.
مدل را به برنامه خود اضافه کنید.
یک فایل SwiftUI جدید به نام ModelDemo.swift
ایجاد کنید.
مانند مراحل قبل، عبارت های import
را برای SwiftUI
و GoogleMaps3D
اضافه کنید.
یک Map
در داخل VStack
در body
خود اعلام کنید.
import SwiftUI
import GoogleMaps3D
struct ModelDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
مسیر مدل را از Bundle خود دریافت کنید. کد این مورد را خارج از struct
اضافه کنید.
private let fileUrl = Bundle.main.url(forResource: "balloon", withExtension: "glb")
یک متغیر برای مدل خود در داخل ساختار اعلان کنید.
یک مقدار پیشفرض در case 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. از مدل با نقشه خود استفاده کنید.
همانند افزودن Marker
، فقط مرجع Model
خود را در اعلان Map
ارائه کنید.
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
balloonModel
}
}
}
برنامه خود را پیش نمایش و اجرا کنید
یک NavigationLink
جدید به GoogleMaps3DDemoApp.swift
، با مقصد ModelDemo()
و Text
"Model Demo" اضافه کنید.
...
NavigationLink(destination: ModelDemo()) {
Text("Model Demo")
}
...
پیش نمایش را بازخوانی کنید یا برنامه خود را اجرا کنید تا مدل را ببینید.
8. روی نقشه خود یک خط و یک چند ضلعی بکشید.
در این مرحله یاد خواهید گرفت که چگونه خطوط و اشکال چند ضلعی را به نقشه سه بعدی خود اضافه کنید.
برای سادگی، اشکال را به عنوان آرایه هایی از اشیاء LatLngAltitude
تعریف می کنید. در یک برنامه واقعی، داده ها ممکن است از یک فایل، یک فراخوانی API یا یک پایگاه داده بارگیری شوند.
برای مدیریت داده های شکل، چند شیء شکل ایجاد کنید.
یک تعریف Camera
جدید به MapHelpers.swift
اضافه کنید که به مرکز شهر سانفرانسیسکو مینگرد.
public static var downtownSanFrancisco: Camera = .init(latitude: 37.7905, longitude: -122.3989, heading: 25, tilt: 71, range: 2500)
یک فایل جدید به نام ShapesDemo.swift
به پروژه خود اضافه کنید. struct
به نام ShapesDemo
اضافه کنید که پروتکل View
را پیاده سازی می کند و body
ای به آن اضافه کنید.
struct ShapesDemo: View {
@State var camera: Camera = .downtownSanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
کلاس هایی که برای مدیریت داده های شکل استفاده خواهید کرد Polyline
و Polygon
هستند. ShapesDemo.swift
باز کرده و به شکل زیر به struct
اضافه کنید.
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) )
به پارامترهای اولیه سازی استفاده شده توجه کنید.
-
altitudeMode: .relativeToGround
برای اکسترود کردن چند ضلعی ها به ارتفاع خاصی از سطح زمین استفاده می شود. -
altitudeMode: .clampToGround
برای اینکه چند خط از شکل سطح زمین پیروی کند استفاده می شود. - استایل ها روی اشیاء
Polygon
با زنجیر کردن یک فراخوانی متد بهstyleOptions()
پس از فراخوانی.init()
تنظیم می شوند.
شکل ها را به نقشه اضافه کنید
درست مانند مراحل قبل، اشکال را می توان مستقیماً به بسته شدن Map
اضافه کرد. Map
خود را در یک VStack
ایجاد کنید.
...
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
polyline
originPolygon
destinationPolygon
}
}
}
...
برنامه خود را پیش نمایش و اجرا کنید
کد پیشنمایش را اضافه کنید و برنامه خود را در قسمت Preview در Xcode بررسی کنید.
#Preview {
ShapesDemo()
}
برای اجرای برنامه خود، یک NavigationLink
جدید به GoogleMaps3DDemoApp.swift
اضافه کنید که نمای دمو جدید را باز می کند.
...
NavigationLink(destination: ShapesDemo()) {
Text("Shapes Demo")
}
...
برنامه خود را اجرا کنید و اشکالی را که اضافه کرده اید کاوش کنید.
9. رویدادهای ضربه زدن را روی نشانگرهای مکان مدیریت کنید
در این مرحله یاد می گیرید که چگونه به ضربه های کاربر روی نشانگرهای مکان پاسخ دهید.
توجه: برای دیدن نشانگرهای مکان روی نقشه، باید MapMode
روی .hybrid
تنظیم کنید.
رسیدگی به شیر به پیاده سازی روش Map.onPlaceTap
نیاز دارد.
رویداد onPlaceTap
یک شی PlaceTapInfo
را ارائه می دهد که از آن می توانید شناسه مکان نشانگر Place ضربه خورده را دریافت کنید.
میتوانید از شناسه مکان برای جستجوی جزئیات بیشتر با استفاده از Places SDK یا Places API استفاده کنید.
یک نمای Swift جدید اضافه کنید
کد زیر را به فایل Swift جدید به نام 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()
}
برنامه خود را پیش نمایش و اجرا کنید
برای پیش نمایش برنامه، صفحه پیش نمایش را باز کنید.
برای اجرای برنامه، یک NavigationLink
جدید به GoogleMaps3DDemoApp.swift
اضافه کنید.
...
NavigationLink(destination: PlaceTapDemo()) {
Text("Place Tap Demo")
}
...
10. (اختیاری) آن را جلوتر ببرید
انیمیشن های دوربین پیشرفته
برخی از موارد استفاده نیاز به متحرک سازی هموار در امتداد یک دنباله یا فهرست مکان ها یا وضعیت های دوربین دارند، به عنوان مثال شبیه ساز پرواز یا پخش مجدد پیاده روی یا دویدن.
در این مرحله یاد می گیرید که چگونه لیستی از مکان ها را از یک فایل بارگذاری کنید و هر مکان را به ترتیب متحرک کنید.
فایلی را بارگیری کنید که حاوی یک دنباله مکان است.
flightpath.json
از مخزن نمونه برنامه GitHub دانلود کنید.
یک پوشه جدید در پروژه Xcode خود به نام JSON
ایجاد کنید.
flightpath.json
به پوشه JSON
خود در Xcode بکشید.
هدف را به عنوان هدف اصلی برنامه خود تنظیم کنید. بررسی کنید که تنظیمات Copy Bundle Resources پروژه شما شامل این فایل باشد.
دو فایل Swift جدید در برنامه خود به نامهای FlightPathData.swift
و FlightDataLoader.swift
ایجاد کنید.
کد زیر را در برنامه خود کپی کنید. این کد ساختارها و کلاس هایی ایجاد می کند که یک فایل محلی به نام "flighpath.json" را می خوانند و آن را به عنوان JSON رمزگشایی می کنند.
ساختارهای FlightPathData
و FlightPathLocation
ساختار داده را در فایل JSON به عنوان اشیاء Swift نشان می دهند.
کلاس FlightDataLoader
داده ها را از فایل می خواند و آن را رمزگشایی می کند. از پروتکل ObservableObject
استفاده می کند تا به برنامه شما اجازه دهد تا تغییرات داده های خود را مشاهده کند.
داده های تجزیه شده از طریق یک ویژگی منتشر شده در معرض دید قرار می گیرند.
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.")
}
}
}
}
}
دوربین را در هر مکان متحرک کنید
برای متحرک سازی دوربین بین یک سری مراحل، از KeyframeAnimator
استفاده می کنید.
هر Keyframe
به عنوان CubicKeyframe
ایجاد می شود CubicKeyframe
، بنابراین تغییرات در وضعیت دوربین به آرامی متحرک می شوند.
استفاده از flyCameraTo()
باعث میشود که نمای بین هر مکان "جهش" پیدا کند.
اول از همه یک دوربین به نام "innsbruck" را در 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)
اکنون یک View جدید را در یک فایل جدید به نام FlyAlongRoute.swift
تنظیم کنید.
SwiftUI
و GoogleMaps3D
را وارد کنید. یک Map
و یک Button
در داخل VStack
اضافه کنید. Button
را برای تغییر وضعیت متغیر animation
Boolean تنظیم کنید.
یک شیء State
برای FlightDataLoader
اعلان کنید، که فایل JSON را با مقداردهی اولیه بارگذاری می کند.
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()
}
}
}
}
فریم های کلیدی را ایجاد کنید
فرآیند اصلی ایجاد تابعی است که یک فریم جدید را در دنباله انیمیشن برمی گرداند. هر فریم جدید وضعیت دوربین بعدی را برای انیماتور مشخص می کند تا به آن متحرک شود. هنگامی که این تابع ایجاد شد، آن را با هر مکان از فایل به ترتیب فراخوانی کنید.
دو تابع به ساختار FlyAlongRoute
خود اضافه کنید. تابع makeKeyFrame
یک CubicKeyframe
با حالت دوربین برمی گرداند. تابع makeCamera
یک مرحله در توالی داده های پرواز برمی دارد و یک شی Camera
را نشان دهنده مرحله برمی گرداند.
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
)
}
انیمیشن را کنار هم قرار دهید
پس از مقداردهی اولیه Map
، keyframeAnimator
فراخوانی کنید و مقادیر اولیه را تنظیم کنید.
شما به حالت اولیه دوربین بر اساس اولین مکان در مسیر پرواز نیاز دارید.
انیمیشن باید بر اساس تغییر حالت متغیر فعال شود.
محتوای keyframeAnimator
باید نقشه باشد.
لیست واقعی فریم های کلیدی با حلقه زدن در هر مکان در مسیر پرواز ایجاد می شود.
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])
}
})
}
)
}
برنامه خود را پیش نمایش و اجرا کنید.
برای پیش نمایش نمای خود، صفحه پیش نمایش را باز کنید.
یک NavigationLink
جدید با مقصد FlightPathDemo()
به GoogleMaps3DDemoApp.swift
اضافه کنید و برنامه را اجرا کنید تا آن را امتحان کنید.
11. تبریک می گویم
شما با موفقیت برنامه ای ساخته اید که
- یک نقشه سه بعدی اولیه را به برنامه شما اضافه می کند.
- نشانگرها، خطوط، چند ضلعی ها و مدل ها را به نقشه شما اضافه می کند.
- کد را برای کنترل دوربین برای پرواز در نقشه و اطراف مکان های خاص پیاده سازی می کند.
چیزی که یاد گرفتی
- چگونه بسته
GoogleMaps3D
را به برنامه Xcode SwiftUI اضافه کنیم. - نحوه مقداردهی اولیه نقشه سه بعدی با کلید API و نمای پیش فرض.
- چگونه نشانگرها، مدل های سه بعدی، خطوط و چند ضلعی را به نقشه خود اضافه کنید.
- چگونه دوربین را کنترل کنیم تا حرکت را به مکان دیگری متحرک کنیم.
- نحوه مدیریت رویدادهای کلیک روی نشانگرهای مکان.
بعدش چی؟
- برای جزئیات بیشتر درباره کارهایی که میتوانید با Maps 3D SDK برای iOS انجام دهید، راهنمای توسعهدهنده را بررسی کنید.
- با پاسخ دادن به نظرسنجی زیر به ما در ایجاد محتوایی که برای شما مفیدتر است کمک کنید: