1. Trước khi bắt đầu
Lớp học lập trình này hướng dẫn bạn cách tạo ứng dụng bản đồ 3D trong SwiftUI bằng SDK Maps 3D dành cho iOS.
Bạn sẽ tìm hiểu:
- Cách điều khiển máy ảnh để xem các địa điểm và bay xung quanh bản đồ.
- Cách thêm điểm đánh dấu và mô hình
- Cách vẽ đường kẻ và đa giác
- Cách xử lý lượt nhấp của người dùng vào điểm đánh dấu Địa điểm.
Điều kiện tiên quyết
- Một dự án trên Google Console đã bật tính năng thanh toán
- Khoá API, có thể được hạn chế cho SDK Maps 3D dành cho iOS.
- Kiến thức cơ bản về cách phát triển iOS bằng SwiftUI.
Bạn sẽ thực hiện
- Thiết lập Xcode và đưa SDK vào bằng Trình quản lý gói Swift
- Định cấu hình ứng dụng để sử dụng khoá API
- Thêm Bản đồ 3D cơ bản vào ứng dụng
- Điều khiển máy ảnh để bay đến và xung quanh các vị trí cụ thể
- Thêm điểm đánh dấu, đường kẻ, đa giác và mô hình vào bản đồ
Bạn cần có
- Xcode 15 trở lên.
2. Bắt đầu thiết lập
Đối với bước bật sau đây, bạn cần bật SDK Maps 3D cho iOS.
Thiết lập Nền tảng Google Maps
Nếu bạn chưa có tài khoản Google Cloud Platform và dự án đã bật tính năng thanh toán, vui lòng xem hướng dẫn Bắt đầu sử dụng Google Maps Platform để tạo tài khoản thanh toán và dự án.
- Trong Cloud Console, hãy nhấp vào trình đơn thả xuống của dự án rồi chọn dự án mà bạn muốn sử dụng cho lớp học lập trình này.
- Bật các API và SDK của Nền tảng Google Maps cần thiết cho lớp học lập trình này trong Google Cloud Marketplace. Để làm như vậy, hãy làm theo các bước trong video này hoặc tài liệu này.
- Tạo khoá API trong trang Thông tin xác thực của Cloud Console. Bạn có thể làm theo các bước trong video này hoặc tài liệu này. Tất cả yêu cầu gửi đến Nền tảng Google Maps đều yêu cầu khoá API.
Bật SDK Maps 3D cho iOS
Bạn có thể tìm thấy SDK Maps 3D cho iOS bằng cách sử dụng đường liên kết trình đơn Google Maps Platform > APIs and Services (Nền tảng Google Maps > API và dịch vụ) trong bảng điều khiển.
Nhấp vào Bật để bật API trên dự án bạn đã chọn.
3. Tạo một ứng dụng SwiftUI cơ bản
Lưu ý: Bạn có thể tìm thấy mã giải pháp cho từng bước trong kho lưu trữ ứng dụng mẫu của lớp học lập trình trên GitHub .
Tạo một ứng dụng mới trong Xcode.
Bạn có thể tìm thấy mã cho bước này trong thư mục GoogleMaps3DDemo trên GitHub.
Mở Xcode và tạo một ứng dụng mới. Chỉ định SwiftUI.
Gọi ứng dụng của bạn là GoogleMaps3DDemo
, với tên gói là com.example.GoogleMaps3DDemo
.
Nhập thư viện GoogleMaps3D vào dự án
Thêm SDK vào dự án bằng Trình quản lý gói Swift.
Trong dự án hoặc không gian làm việc Xcode, hãy chuyển đến Tệp > Thêm phần phụ thuộc gói. Nhập https://github.com/googlemaps/ios-maps-3d-sdk làm URL, nhấn Enter để lấy gói rồi nhấp vào "Thêm gói".
Trong cửa sổ Choose Package Products (Chọn sản phẩm gói), hãy xác minh rằng GoogleMaps3D
sẽ được thêm vào mục tiêu chính đã chỉ định. Sau khi hoàn tất, hãy nhấp vào Thêm gói.
Để xác minh quá trình cài đặt, hãy chuyển đến ngăn General (Chung) của mục tiêu. Trong khung, thư viện và nội dung nhúng, bạn sẽ thấy các gói đã cài đặt. Bạn cũng có thể xem mục Phần phụ thuộc gói của Trình điều hướng dự án để xác minh gói và phiên bản của gói.
Thêm khoá API
Bạn có thể mã hoá cứng khoá API vào ứng dụng, nhưng đây không phải là phương pháp hay. Việc thêm tệp cấu hình cho phép bạn giữ bí mật Khoá API và tránh kiểm tra khoá đó vào hệ thống quản lý nguồn.
Tạo tệp cấu hình mới trong thư mục gốc của dự án
Trong Xcode, hãy đảm bảo bạn đang xem cửa sổ trình khám phá dự án. Nhấp chuột phải vào thư mục gốc của dự án rồi chọn "New File from Template" (Tệp mới từ mẫu). Cuộn cho đến khi bạn thấy "Tệp cài đặt cấu hình". Chọn mục này rồi nhấp vào "Tiếp theo". Đặt tên tệp là Config.xcconfig
và đảm bảo bạn đã chọn thư mục gốc của dự án. Nhấp vào "Tạo" để tạo tệp.
Trong trình chỉnh sửa, hãy thêm một dòng vào tệp cấu hình như sau: MAPS_API_KEY = YOUR_API_KEY
Thay thế YOUR_API_KEY
bằng khoá API của bạn.
Thêm chế độ cài đặt này vào Info.plist
.
Để làm việc này, hãy chọn thư mục gốc của dự án rồi nhấp vào thẻ "Thông tin".
Thêm một thuộc tính mới có tên là MAPS_API_KEY
với giá trị là $(MAPS_API_KEY)
.
Mã ứng dụng mẫu có tệp Info.plist
chỉ định thuộc tính này.
Thêm bản đồ
Mở tệp có tên GoogleMaps3DDemoApp.swift
. Đây là điểm truy cập và bảng điều hướng chính cho ứng dụng của bạn.
Hàm này gọi ContentView()
để hiển thị thông báo Hello World (Xin chào thế giới).
Mở ContentView.swift
trong trình chỉnh sửa.
Thêm câu lệnh import
cho GoogleMaps3D
.
Xoá mã bên trong khối mã var body: some View {}
. Khai báo một Map()
mới bên trong body
.
Cấu hình tối thiểu bạn cần để khởi chạy Map
là MapMode
. Thuộc tính này có thể có hai giá trị:
.hybrid
– hình ảnh vệ tinh có đường và nhãn, hoặc.satellite
– chỉ hình ảnh vệ tinh.
Hãy chọn .hybrid
.
Tệp ContentView.swift
của bạn sẽ có dạng như sau.
import GoogleMaps3D
import SwiftUI
@main
struct ContentView: View {
var body: some View {
Map(mode: .hybrid)
}
}
Đặt khoá API.
Bạn phải đặt khoá API trước khi Bản đồ khởi chạy.
Bạn có thể thực hiện việc này bằng cách đặt Map.apiKey
trong trình xử lý sự kiện init()
của bất kỳ View
nào chứa Bản đồ. Bạn cũng có thể đặt giá trị này trong GoogleMaps3DDemoApp.swift
trước khi gọi ContentView()
.
Trong GoogleMaps3DDemoApp.swift
, hãy đặt Map.apiKey
trong trình xử lý sự kiện onAppear
của WindowGroup
.
Tìm nạp khoá API từ tệp cấu hình
Sử dụng Bundle.main.infoDictionary
để truy cập vào chế độ cài đặt MAPS_API_KEY
mà bạn đã tạo trong tệp cấu hình.
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
}
}
}
Tạo và chạy ứng dụng để kiểm tra xem ứng dụng có tải đúng cách không. Bạn sẽ thấy bản đồ thế giới.
4. Sử dụng máy ảnh để điều khiển chế độ xem bản đồ
Tạo đối tượng trạng thái máy ảnh
Chế độ xem Bản đồ 3D được kiểm soát bởi lớp Camera
. Ở bước này, bạn sẽ tìm hiểu cách chỉ định vị trí, độ cao, hướng, độ nghiêng, độ nghiêng và phạm vi để tuỳ chỉnh chế độ xem bản đồ.
Tạo lớp Trợ giúp để lưu trữ chế độ cài đặt Máy ảnh
Thêm một tệp trống mới có tên là MapHelpers.swift
. Trong tệp mới, hãy nhập GoogleMaps3D
và thêm một phần mở rộng vào lớp Camera
. Thêm một biến có tên là sanFrancisco
. Khởi tạo biến này dưới dạng đối tượng Camera
mới. Tìm máy ảnh tại latitude: 37.39, longitude: -122.08
.
import GoogleMaps3D
extension Camera {
public static var sanFrancisco: Camera = .init(latitude: 37.39, longitude: -122.08)
}
Thêm Thành phần hiển thị mới vào ứng dụng
Tạo một tệp mới có tên là CameraDemo.swift
. Thêm bản phác thảo cơ bản của Chế độ xem SwiftUI mới vào tệp.
Thêm biến @State
có tên là camera
thuộc loại Camera
. Khởi chạy biến này thành máy ảnh sanFrancisco
mà bạn vừa xác định.
Việc sử dụng @State
cho phép bạn liên kết Bản đồ với trạng thái máy ảnh và sử dụng bản đồ đó làm nguồn đáng tin cậy.
@State var camera: Camera = .sanFrancisco
Thay đổi lệnh gọi hàm Map()
để thêm thuộc tính camera
. Sử dụng liên kết trạng thái máy ảnh $camera
để khởi chạy thuộc tính camera
cho đối tượng Máy ảnh @State
(.sanFrancisco
).
import SwiftUI
import GoogleMaps3D
struct CameraDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
Thêm giao diện người dùng điều hướng cơ bản vào ứng dụng
Thêm NavigationView
vào điểm truy cập chính của ứng dụng, GoogleMaps3DDemoApp.swift
.
Thao tác này sẽ cho phép người dùng xem danh sách bản minh hoạ và nhấp vào từng bản minh hoạ để mở.
Chỉnh sửa GoogleMaps3DDemoApp.swift
để thêm NavigationView
mới.
Thêm List
chứa hai phần khai báo NavigationLink
.
NavigationLink
đầu tiên sẽ mở ContentView()
với nội dung mô tả Text
Basic Map
.
NavigationLink
thứ hai sẽ mở CameraDemo()
.
...
NavigationView {
List {
NavigationLink(destination: ContentView()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
}
}
...
Thêm bản xem trước Xcode
Bản xem trước là một tính năng mạnh mẽ của Xcode, cho phép bạn xem và tương tác với ứng dụng khi thực hiện thay đổi đối với ứng dụng đó.
Để thêm bản xem trước, hãy mở CameraDemo.swift
. Thêm một khối mã #Preview {}
bên ngoài struct
.
#Preview {
CameraDemo()
}
Mở hoặc làm mới ngăn Xem trước trong Xcode. Bản đồ sẽ hiển thị San Francisco.
Thiết lập chế độ xem 3D tuỳ chỉnh
Bạn có thể chỉ định các tham số bổ sung để điều khiển máy ảnh:
heading
: góc phương vị tính theo độ từ hướng bắc để hướng máy ảnh.tilt
: góc nghiêng tính bằng độ, trong đó 0 là trực tiếp phía trên đầu và 90 là nhìn theo chiều ngang.roll
: góc nghiêng xung quanh mặt phẳng dọc của máy ảnh, tính bằng độrange
: khoảng cách tính bằng mét của máy ảnh từ vị trí vĩ độ, kinh độaltitude
: chiều cao của máy ảnh so với mực nước biển
Nếu bạn không cung cấp bất kỳ thông số bổ sung nào trong số này, hệ thống sẽ sử dụng giá trị mặc định.
Để chế độ xem máy ảnh hiển thị nhiều dữ liệu 3D hơn, hãy đặt các thông số ban đầu để hiển thị chế độ xem nghiêng, gần hơn.
Chỉnh sửa Camera
mà bạn đã xác định trong MapHelpers.swift
để thêm các giá trị cho altitude
, heading
, tilt
, roll
và 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)
Tạo bản dựng và chạy ứng dụng để xem và khám phá chế độ xem 3D mới.
5. Ảnh động cơ bản của máy ảnh
Cho đến nay, bạn đã sử dụng máy ảnh để chỉ định một vị trí duy nhất có độ nghiêng, độ cao, hướng và phạm vi. Trong bước này, bạn sẽ tìm hiểu cách di chuyển chế độ xem máy ảnh bằng cách tạo ảnh động cho các thuộc tính này từ trạng thái ban đầu sang trạng thái mới.
Bay đến một vị trí
Bạn sẽ sử dụng phương thức Map.flyCameraTo()
để tạo ảnh động cho máy ảnh từ vị trí ban đầu đến vị trí mới.
Phương thức flyCameraTo()
có một số tham số:
Camera
đại diện cho vị trí kết thúc.duration
: Thời lượng chạy ảnh động, tính bằng giây.trigger
: một đối tượng có thể quan sát được sẽ kích hoạt ảnh động khi trạng thái của đối tượng đó thay đổi.completion
: mã sẽ được thực thi khi ảnh động hoàn tất.
Xác định một vị trí để bay đến
Mở tệp MapHelpers.swift
.
Xác định một đối tượng máy ảnh mới để hiển thị Seattle.
public static var seattle: Camera = .init(latitude:
47.6210296,longitude: -122.3496903, heading: 149.0, tilt: 77.0, roll: 0.0, range: 4000)
Thêm một nút để kích hoạt ảnh động.
Mở CameraDemo.swift
. Khai báo một biến Boolean mới bên trong struct
.
Gọi biến này là animate
với giá trị ban đầu là false
.
@State private var animate: Bool = false
Thêm Button
bên dưới VStack
. Button
sẽ bắt đầu ảnh động bản đồ.
Cung cấp cho Button
một số Text
thích hợp, chẳng hạn như "Start Flying" (Bắt đầu bay).
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") {
}
}
}
}
Trong phần đóng Nút, hãy thêm mã để bật/tắt trạng thái của biến animate
.
Button("Start Flying") {
animate.toggle()
}
Bắt đầu ảnh động.
Thêm mã để kích hoạt ảnh động flyCameraTo()
khi trạng thái của biến animate
thay đổi.
var body: some View {
VStack{
Map(camera: $camera, mode: .hybrid)
.flyCameraTo(
.seattle,
duration: 5,
trigger: animate,
completion: { }
)
Button("Start Flying") {
animate.toggle()
}
}
}
Bay xung quanh một vị trí
Bạn có thể bay xung quanh một vị trí bằng cách sử dụng phương thức Map.flyCameraAround()
. Phương thức này có một số tham số:
Camera
xác định vị trí và chế độ xem.duration
tính bằng giây.rounds
: số lần lặp lại ảnh động.trigger
: một đối tượng có thể quan sát sẽ kích hoạt ảnh động.callback
: mã sẽ thực thi khi ảnh động chạy.
Xác định một biến @State
mới có tên là flyAround
, với giá trị ban đầu là false
.
Khi bạn đã thực hiện việc đó, hãy thêm lệnh gọi đến flyCameraAround()
ngay sau lệnh gọi phương thức flyCameraTo()
.
Thời lượng bay xung quanh phải tương đối dài để chế độ xem thay đổi một cách mượt mà.
Hãy nhớ kích hoạt ảnh động flyCameraAround()
bằng cách thay đổi trạng thái của đối tượng điều kiện kích hoạt khi flyCameraTo()
hoàn tất.
Mã của bạn sẽ có dạng như thế này.
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()
}
Xem trước hoặc chạy ứng dụng để thấy máy ảnh bay xung quanh đích đến sau khi ảnh động flyCameraTo()
hoàn tất.
6. Thêm Điểm đánh dấu vào bản đồ.
Trong bước này, bạn sẽ tìm hiểu cách vẽ một ghim điểm đánh dấu trên bản đồ.
Bạn sẽ tạo một đối tượng Marker
và thêm đối tượng đó vào bản đồ. SDK sẽ sử dụng biểu tượng mặc định cho điểm đánh dấu. Cuối cùng, bạn sẽ điều chỉnh độ cao của điểm đánh dấu và các thuộc tính khác để thay đổi cách hiển thị điểm đánh dấu.
Tạo một Chế độ xem SwiftUI mới cho bản minh hoạ về Điểm đánh dấu.
Thêm một tệp Swift mới vào dự án. Đặt tên là MarkerDemo.swift
.
Thêm đường viền của Chế độ xem SwiftUI và khởi chạy bản đồ như bạn đã làm trong CameraDemo
.
import SwiftUI
import GoogleMaps3D
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid)
}
}
}
Khởi tạo đối tượng Điểm đánh dấu
Khai báo biến điểm đánh dấu mới có tên là mapMarker
. Ở đầu khối mã struct
trong MarkerDemo.swift
.
Đặt định nghĩa trên dòng bên dưới phần khai báo camera
. Mã mẫu này khởi tạo tất cả các thuộc tính có sẵn.
@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"
)
Thêm Điểm đánh dấu vào bản đồ.
Để vẽ điểm đánh dấu, hãy thêm điểm đánh dấu đó vào một hàm đóng được gọi khi tạo Bản đồ.
struct MarkerDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
mapMarker
}
}
}
}
Thêm NavigationLink
mới vào GoogleMaps3DDemoApp.swift
với đích đến là MarkerDemo()
và Text
mô tả đích đến đó là "Marker Demo" (Bản minh hoạ điểm đánh dấu).
...
NavigationView {
List {
NavigationLink(destination: Map()) {
Text("Basic Map")
}
NavigationLink(destination: CameraDemo()) {
Text("Camera Demo")
}
NavigationLink(destination: MarkerDemo()) {
Text("Marker Demo")
}
}
}
...
Xem trước và chạy Ứng dụng
Làm mới bản xem trước hoặc chạy ứng dụng để xem điểm đánh dấu.
Điểm đánh dấu được đẩy ra
Bạn có thể đặt điểm đánh dấu phía trên mặt đất hoặc lưới 3D bằng altitude
và altitudeMode
.
Sao chép nội dung khai báo mapMarker
trong MarkerDemo.swift
vào một biến Marker
mới có tên là extrudedMarker
.
Đặt giá trị khác 0 cho altitude
, 50 là đủ.
Thay đổi altitudeMode
thành .relativeToMesh
và đặt extruded
thành true
. Sử dụng latitude
và longitude
trong đoạn mã tại đây để đặt điểm đánh dấu trên đỉnh một tòa nhà chọc trời.
@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"
)
Chạy hoặc xem trước lại ứng dụng. Điểm đánh dấu sẽ xuất hiện trên một toà nhà 3D.
7. Thêm mô hình vào bản đồ.
Bạn có thể thêm Model
theo cách tương tự như Marker
. Bạn sẽ cần một tệp mô hình có thể truy cập bằng URL hoặc thêm dưới dạng tệp cục bộ trong dự án. Ở bước này, chúng ta sẽ sử dụng một tệp cục bộ mà bạn có thể tải xuống từ kho lưu trữ GitHub cho lớp học lập trình này.
Thêm tệp mô hình vào dự án
Tạo một thư mục mới trong dự án Xcode có tên là Models
.
Tải mô hình xuống từ kho lưu trữ ứng dụng mẫu trên GitHub. Thêm tệp này vào dự án bằng cách kéo tệp đó vào thư mục mới trong chế độ xem dự án Xcode.
Hãy nhớ đặt mục tiêu này làm mục tiêu chính cho ứng dụng của bạn.
Kiểm tra chế độ cài đặt Build Phases (Giai đoạn xây dựng) > Copy Bundle Resources (Sao chép tài nguyên gói) cho dự án của bạn. Tệp mô hình phải nằm trong danh sách tài nguyên được sao chép vào gói. Nếu không thấy, hãy nhấp vào "+" để thêm.
Thêm mô hình vào ứng dụng.
Tạo một tệp SwiftUI mới có tên ModelDemo.swift
.
Thêm câu lệnh import
cho SwiftUI
và GoogleMaps3D
như trong các bước trước.
Khai báo Map
bên trong VStack
trong body
.
import SwiftUI
import GoogleMaps3D
struct ModelDemo: View {
@State var camera: Camera = .sanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
Lấy đường dẫn mô hình từ Gói của bạn. Thêm mã cho việc này bên ngoài struct
.
private let fileUrl = Bundle.main.url(forResource: "balloon", withExtension: "glb")
Khai báo một biến cho mô hình của bạn bên trong cấu trúc.
Cung cấp giá trị mặc định trong trường hợp không cung cấp 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. Sử dụng mô hình này với Bản đồ của bạn.
Tương tự như khi thêm Marker
, bạn chỉ cần cung cấp tham chiếu đến Model
trong phần khai báo Map
.
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
balloonModel
}
}
}
Xem trước và chạy ứng dụng
Thêm NavigationLink
mới vào GoogleMaps3DDemoApp.swift
, với đích đến là ModelDemo()
và Text
"Mô hình minh hoạ".
...
NavigationLink(destination: ModelDemo()) {
Text("Model Demo")
}
...
Làm mới bản xem trước hoặc chạy ứng dụng để xem mô hình.
8. Vẽ một đường kẻ và một đa giác trên bản đồ.
Trong bước này, bạn sẽ tìm hiểu cách thêm đường kẻ và hình đa giác vào bản đồ 3D.
Để đơn giản, bạn sẽ xác định các hình dạng dưới dạng mảng của các đối tượng LatLngAltitude
. Trong một ứng dụng thực tế, dữ liệu có thể được tải từ một tệp, lệnh gọi API hoặc cơ sở dữ liệu.
Tạo một số đối tượng hình dạng để quản lý dữ liệu hình dạng.
Thêm định nghĩa Camera
mới vào MapHelpers.swift
để xem trung tâm thành phố San Francisco.
public static var downtownSanFrancisco: Camera = .init(latitude: 37.7905, longitude: -122.3989, heading: 25, tilt: 71, range: 2500)
Thêm một tệp mới vào dự án có tên là ShapesDemo.swift
. Thêm một struct
có tên là ShapesDemo
để triển khai giao thức View
và thêm một body
vào đó.
struct ShapesDemo: View {
@State var camera: Camera = .downtownSanFrancisco
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
}
}
}
}
Các lớp bạn sẽ sử dụng để quản lý dữ liệu hình dạng là Polyline
và Polygon
. Mở ShapesDemo.swift
và thêm các lớp này vào struct
như sau.
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) )
Lưu ý các tham số khởi chạy được sử dụng.
altitudeMode: .relativeToGround
được dùng để đẩy các đa giác lên một độ cao cụ thể so với mặt đất.altitudeMode: .clampToGround
được dùng để tạo đường đa tuyến tuân theo hình dạng của bề mặt trái đất.- các kiểu được đặt trên đối tượng
Polygon
bằng cách tạo chuỗi cho lệnh gọi phương thức đếnstyleOptions()
sau khi.init()
được gọi
Thêm hình dạng vào Bản đồ
Giống như trong các bước trước, bạn có thể thêm trực tiếp các hình dạng vào phần đóng Map
. Tạo Map
bên trong VStack
.
...
var body: some View {
VStack {
Map(camera: $camera, mode: .hybrid) {
polyline
originPolygon
destinationPolygon
}
}
}
...
Xem trước và chạy ứng dụng
Thêm mã Xem trước và kiểm tra ứng dụng trong ngăn Xem trước trong Xcode.
#Preview {
ShapesDemo()
}
Để chạy ứng dụng, hãy thêm một NavigationLink
mới vào GoogleMaps3DDemoApp.swift
để mở Chế độ xem minh hoạ mới.
...
NavigationLink(destination: ShapesDemo()) {
Text("Shapes Demo")
}
...
Chạy ứng dụng và khám phá các hình dạng bạn đã thêm.
9. Xử lý sự kiện nhấn trên Điểm đánh dấu địa điểm
Trong bước này, bạn sẽ tìm hiểu cách phản hồi thao tác nhấn của người dùng vào điểm đánh dấu Địa điểm.
Lưu ý: Để xem điểm đánh dấu Địa điểm trên bản đồ, bạn cần đặt MapMode
thành .hybrid
.
Để xử lý thao tác nhấn, bạn cần triển khai phương thức Map.onPlaceTap
.
Sự kiện onPlaceTap
cung cấp một đối tượng PlaceTapInfo
mà bạn có thể lấy Mã địa điểm của điểm đánh dấu Địa điểm đã nhấn.
Bạn có thể sử dụng Mã địa điểm để tra cứu thêm thông tin chi tiết bằng SDK Địa điểm hoặc API Địa điểm.
Thêm Chế độ xem Swift mới
Thêm mã sau vào tệp Swift mới có tên 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()
}
Xem trước và chạy Ứng dụng
Mở ngăn Xem trước để xem trước ứng dụng.
Để chạy ứng dụng, hãy thêm một NavigationLink
mới vào GoogleMaps3DDemoApp.swift
.
...
NavigationLink(destination: PlaceTapDemo()) {
Text("Place Tap Demo")
}
...
10. (Không bắt buộc) Mở rộng phạm vi
Ảnh động nâng cao của Máy ảnh
Một số trường hợp sử dụng yêu cầu tạo ảnh động mượt mà theo một trình tự hoặc danh sách vị trí hoặc trạng thái máy ảnh, ví dụ: trình mô phỏng chuyến bay hoặc phát lại một chuyến đi bộ đường dài hoặc chạy bộ.
Trong bước này, bạn sẽ tìm hiểu cách tải danh sách vị trí từ một tệp và tạo ảnh động cho từng vị trí theo trình tự.
Tải tệp chứa một trình tự vị trí.
Tải flightpath.json
xuống từ kho lưu trữ ứng dụng mẫu GitHub.
Tạo một thư mục mới trong dự án Xcode có tên là JSON
.
Kéo flightpath.json
vào thư mục JSON
trong Xcode.
Đặt mục tiêu này làm mục tiêu chính của ứng dụng. Kiểm tra để đảm bảo rằng chế độ cài đặt Copy Bundle Resources (Sao chép tài nguyên gói) của dự án có tệp này.
Tạo hai tệp Swift mới trong ứng dụng có tên là FlightPathData.swift
và FlightDataLoader.swift
.
Sao chép mã sau vào ứng dụng của bạn. Mã này tạo các cấu trúc và lớp đọc tệp cục bộ có tên "flighpath.json" và giải mã tệp đó dưới dạng JSON.
Cấu trúc FlightPathData
và FlightPathLocation
đại diện cho cấu trúc dữ liệu trong tệp JSON dưới dạng đối tượng Swift.
Lớp FlightDataLoader
đọc dữ liệu từ tệp và giải mã dữ liệu đó. API này sử dụng giao thức ObservableObject
để cho phép ứng dụng của bạn quan sát các thay đổi đối với dữ liệu của ứng dụng.
Dữ liệu được phân tích cú pháp được hiển thị thông qua một thuộc tính đã xuất bản.
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.")
}
}
}
}
}
Tạo ảnh động cho máy ảnh dọc theo từng vị trí
Để tạo ảnh động cho máy ảnh giữa một chuỗi các bước, bạn sẽ sử dụng KeyframeAnimator
.
Mỗi Keyframe
sẽ được tạo dưới dạng CubicKeyframe
, vì vậy, các thay đổi về trạng thái máy ảnh sẽ được tạo ảnh động một cách mượt mà.
Việc sử dụng flyCameraTo()
sẽ khiến thành phần hiển thị "bật lại" giữa mỗi vị trí.
Trước tiên, hãy khai báo một camera có tên "innsbruck" trong 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)
Bây giờ, hãy thiết lập một Chế độ xem mới trong tệp mới có tên FlyAlongRoute.swift
.
Nhập SwiftUI
và GoogleMaps3D
. Thêm Map
và Button
vào bên trong VStack
. Thiết lập Button
để bật/tắt trạng thái của biến Boolean animation
.
Khai báo đối tượng State
cho FlightDataLoader
. Đối tượng này sẽ tải tệp JSON khi được khởi tạo.
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()
}
}
}
}
Tạo khung hình chính
Quy trình cơ bản là tạo một hàm trả về một khung hình mới trong trình tự ảnh động. Mỗi khung hình mới xác định trạng thái máy ảnh tiếp theo để ảnh động chuyển đến. Sau khi tạo hàm này, hãy gọi hàm đó theo trình tự với từng vị trí trong tệp.
Thêm hai hàm vào cấu trúc FlyAlongRoute
. Hàm makeKeyFrame
trả về CubicKeyframe
có trạng thái Máy ảnh. Hàm makeCamera
thực hiện một bước trong trình tự dữ liệu chuyến bay và trả về một đối tượng Camera
đại diện cho bước đó.
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
)
}
Kết hợp ảnh động
Gọi keyframeAnimator
sau khi khởi chạy Map
và đặt các giá trị ban đầu.
Bạn sẽ cần có trạng thái máy ảnh ban đầu dựa trên vị trí đầu tiên trong đường bay.
Ảnh động sẽ kích hoạt dựa trên trạng thái thay đổi của biến.
Nội dung keyframeAnimator
phải là một Bản đồ.
Danh sách khung hình chính thực tế được tạo bằng cách lặp lại từng vị trí trong đường bay.
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])
}
})
}
)
}
Xem trước và chạy ứng dụng.
Mở ngăn Xem trước để xem trước Chế độ xem.
Thêm một NavigationLink
mới có đích đến là FlightPathDemo()
vào GoogleMaps3DDemoApp.swift
và chạy ứng dụng để thử nghiệm.
11. Xin chúc mừng
Bạn đã tạo thành công một ứng dụng
- Thêm Bản đồ 3D cơ bản vào ứng dụng.
- Thêm điểm đánh dấu, đường kẻ, đa giác và mô hình vào bản đồ.
- Triển khai mã để điều khiển máy ảnh bay qua bản đồ và xung quanh các vị trí cụ thể.
Kiến thức bạn học được
- Cách thêm gói
GoogleMaps3D
vào Ứng dụng SwiftUI Xcode. - Cách khởi tạo Bản đồ 3D bằng Khoá API và chế độ xem mặc định.
- Cách thêm điểm đánh dấu, mô hình 3D, đường kẻ và đa giác vào bản đồ.
- Cách kiểm soát máy ảnh để tạo ảnh động cho chuyển động đến một vị trí khác.
- Cách xử lý sự kiện nhấp chuột trên Điểm đánh dấu địa điểm.
Tiếp theo là gì?
- Hãy xem hướng dẫn dành cho nhà phát triển để biết thêm thông tin chi tiết về những việc bạn có thể làm với SDK Maps 3D dành cho iOS.
- Hãy giúp chúng tôi tạo ra nội dung mà bạn thấy hữu ích nhất bằng cách trả lời bản khảo sát sau: