Mapbox Directions for Swift
Mapbox Directions for Swift(之前称为 MapboxDirections.swift)使您的 iOS、macOS、tvOS、watchOS 或 Linux 应用程序能够轻松连接到 Mapbox Directions 和 Map Matching API。快速获取驾驶、骑行或步行路线,无论是直达还是有多处停留点,都可以通过一个简单界面的 MapKit 的 MKDirections
API。将 GPX 跟踪拟合到 OpenStreetMap 道路网络。Mapbox Directions 和 Map Matching API 由 OSRM 和 Valhalla 路由引擎提供支持。有关更多信息,请参阅 Mapbox Navigation 主页。
Mapbox Directions 与 MapboxGeocoder.swift、MapboxStatic.swift、iOS 的 Mapbox Navigation SDK 以及 iOS 的 Mapbox Maps SDK 或 macOS SDK 一起使用效果良好。
入门
在您的 Carthage Cartfile 中指定以下依赖项
# Latest stable release
github "mapbox/mapbox-directions-swift" ~> 2.9
# Latest prerelease
github "mapbox/mapbox-directions-swift" "v2.11.0-rc.1"
或者在你的 CocoaPods Podfile 中
# Latest stable release
pod 'MapboxDirections', '~> 2.9'
# Latest prerelease
pod 'MapboxDirections', :git => 'https://github.com/mapbox/mapbox-directions-swift.git', :tag => 'v2.11.0-rc.1'
或者在你的 Swift Package Manager Package.swift 中
// Latest stable release
.package(name: "MapboxDirections", url: "https://github.com/mapbox/mapbox-directions-swift.git", from: "2.9.1")
// Latest prerelease
.package(name: "MapboxDirections", url: "https://github.com/mapbox/mapbox-directions-swift.git", .exact("2.11.0-rc.1"))
然后 import MapboxDirections
。
此仓库包含一个示例应用程序,展示如何使用该框架。要运行它,您需要使用 Carthage 0.19 或更高版本来安装依赖项。更详细的文档可在Mapbox API 文档中找到。
系统需求
- 以下之一的高级管理包
- CocoaPods 1.10 或更高版本
- Carthage 0.38 或更高版本
- Swift 包管理器 5.5 或更高版本
- Xcode 13 或更高版本
- 以下之一的操作系统
- iOS 12.0 或更高版本
- macOS 10.14 或更高版本
- tvOS 12.0 或更高版本
- watchOS 5.0 或更高版本
- 任何支持 Swift 的 Linux 发行版
0.30.0 是 MapboxDirections.swift 最后一个支持最小部署目标为 iOS 9.x、macOS 10.11.x、tvOS 9.x 或 watchOS 2.x 的版本。0.30.0 也是最后一个与 Objective-C 或 AppleScript 代码兼容的版本。
用法
为了使用 API,您需要Mapbox 访问令牌。如果您已经使用了Mapbox Maps SDK for iOS或macOS SDK,只要您已将令牌放置在应用程序的 Info.plist 文件的 MBXAccessToken 键中,Mapbox Directions 就会自动识别您的访问令牌。
以下示例均以 Swift 编写(标识为 main.swift)。有关详细信息,请参阅发布中提供的文档。
在位置之间计算方向
主要方向类是 Directions
。使用您的访问令牌创建方向对象
// main.swift
import MapboxDirections
let directions = Directions(credentials: Credentials(accessToken: "<#your access token#>"))
或者,您也可以将访问令牌放置在应用程序的 Info.plist 文件中的 MBXAccessToken 键中,然后使用共享方向对象
// main.swift
let directions = Directions.shared
拿着 directions 对象,构造一个 RouteOptions 对象,并将它传递给 Directions.calculate(_:completionHandler:)
方法。
// main.swift
let waypoints = [
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox"),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House"),
]
let options = RouteOptions(waypoints: waypoints, profileIdentifier: .automobileAvoidingTraffic)
options.includesSteps = true
let task = directions.calculate(options) { (session, result) in
switch result {
case .failure(let error):
print("Error calculating directions: \(error)")
case .success(let response):
guard let route = response.routes?.first, let leg = route.legs.first else {
return
}
print("Route via \(leg):")
let distanceFormatter = LengthFormatter()
let formattedDistance = distanceFormatter.string(fromMeters: route.distance)
let travelTimeFormatter = DateComponentsFormatter()
travelTimeFormatter.unitsStyle = .short
let formattedTravelTime = travelTimeFormatter.string(from: route.expectedTravelTime)
print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)")
for step in leg.steps {
print("\(step.instructions)")
let formattedDistance = distanceFormatter.string(fromMeters: step.distance)
print("— \(formattedDistance) —")
}
}
}
该库默认使用 Mapbox Directions API 的第 5 版。
将轨迹与路网匹配
如果您有 GPX 轨迹或其他 GPS 导出的位置数据,可以使用 Map Matching API 清理数据并将其匹配到路网。
// main.swift
let coordinates = [
CLLocationCoordinate2D(latitude: 32.712041, longitude: -117.172836),
CLLocationCoordinate2D(latitude: 32.712256, longitude: -117.17291),
CLLocationCoordinate2D(latitude: 32.712444, longitude: -117.17292),
CLLocationCoordinate2D(latitude: 32.71257, longitude: -117.172922),
CLLocationCoordinate2D(latitude: 32.7126, longitude: -117.172985),
CLLocationCoordinate2D(latitude: 32.712597, longitude: -117.173143),
CLLocationCoordinate2D(latitude: 32.712546, longitude: -117.173345)
]
let options = MatchOptions(coordinates: coordinates)
options.includesSteps = true
let task = directions.calculate(options) { (session, result) in
switch result {
case .failure(let error):
print("Error matching coordinates: \(error)")
case .success(let response):
guard let match = response.matches?.first, let leg = match.legs.first else {
return
}
print("Match via \(leg):")
let distanceFormatter = LengthFormatter()
let formattedDistance = distanceFormatter.string(fromMeters: match.distance)
let travelTimeFormatter = DateComponentsFormatter()
travelTimeFormatter.unitsStyle = .short
let formattedTravelTime = travelTimeFormatter.string(from: match.expectedTravelTime)
print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)")
for step in leg.steps {
print("\(step.instructions)")
let formattedDistance = distanceFormatter.string(fromMeters: step.distance)
print("— \(formattedDistance) —")
}
}
}
您还可以使用 Directions.calculateRoutes(matching:completionHandler:)
方法来获取与标准 Directions API 响应类似的路由对象。
创建等时线地图
使用等时线 API 告诉用户,他们可以在给定位置一定距离或时间内走多远。 Isochrone
使用与 Directions
相同的访问令牌初始化。设置好后,需要填写 IsochroneOptions
参数来计算所需的 GeoJSON。
let isochrones = Isochrones(credentials: Credentials(accessToken: "<#your access token#>"))
let isochroneOptions = IsochroneOptions(centerCoordinate: CLLocationCoordinate2D(latitude: 45.52, longitude: -122.681944),
contours: .byDistances([
.init(value: 500, unit: .meters, color: .orange),
.init(value: 1, unit: .kilometers, color: .red)
]))
isochrones.calculate(isochroneOptions) { session, result in
if case .success(let response) = result {
print(response)
}
}
检索距离或持续时间矩阵
使用 Matrix API 查看多个点之间的旅行时间或距离。 Matrix
使用与 Directions
相同的访问令牌初始化。配置好后,需要填写 MatrixOptions
参数来计算所需的矩阵。
let matrix = Matrix(credentials: Credentials(accessToken: "<#your access token#>")
let waypoints = [
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.751668, longitude: -122.418408), name: "Mission Street"),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.755184, longitude: -122.422959), name: "22nd Street"),
Waypoint(coordinate: CLLocationCoordinate2D(latitude: 37.759695, longitude: -122.426911))
]
let matrixOptions = MatrixOptions(sources: waypoints, destinations: waypoints, profileIdentifier: .automobile)
matrix.calculate(matrixOptions) { session, result in
if case .success(let response) = result,
let expectedTravelTime = response.travelTime(from: 0, to: 1) {
print("Expected route duration from '\(waypoints[0].name)' to '\(waypoints[1].name)' is \(expectedTravelTime / 60) minutes.")
}
}
使用其他 Mapbox 库
在地图上绘制路线
使用Mapbox Maps SDK for iOS 或macOS SDK,您可以在地图上轻松绘制路线。
// main.swift
if var routeCoordinates = route.shape?.coordinates, routeCoordinates.count > 0 {
// Convert the route’s coordinates into a polyline.
let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: UInt(routeCoordinates.count))
// Add the polyline to the map.
mapView.addAnnotation(routeLine)
// Fit the viewport to the polyline.
let camera = mapView.cameraThatFitsShape(routeLine, direction: 0, edgePadding: .zero)
mapView.setCamera(camera, animated: true)
}
展示逐点导航界面
Mapbox Navigation SDK for iOS 提供了通过 MapboxDirections 提供的路线进行逐点导航的完整用户界面。
在地图快照上绘制等时线轮廓
MapboxStatic.swift 提供了在地图上绘制等时线轮廓的简单方法。
// main.swift
import MapboxStatic
import MapboxDirections
let centerCoordinate = CLLocationCoordinate2D(latitude: 45.52, longitude: -122.681944)
let accessToken = "<#your access token#>"
// Setup snapshot parameters
let camera = SnapshotCamera(
lookingAtCenter: centerCoordinate,
zoomLevel: 12)
let options = SnapshotOptions(
styleURL: URL(string: "<#your mapbox: style URL#>")!,
camera: camera,
size: CGSize(width: 200, height: 200))
// Request Isochrone contour to draw on a map
let isochrones = Isochrones(credentials: Credentials(accessToken: accessToken))
isochrones.calculate(IsochroneOptions(centerCoordinate: centerCoordinate,
contours: .byDistances([.init(value: 500, unit: .meters)]))) { session, result in
if case .success(let response) = result {
// Serialize the geoJSON
let encoder = JSONEncoder()
let data = try! encoder.encode(response)
let geoJSONString = String(data: data, encoding: .utf8)!
let geoJSONOverlay = GeoJSON(objectString: geoJSONString)
// Feed resulting geoJSON to snapshot options
options.overlays.append(geoJSONOverlay)
let snapshot = Snapshot(
options: options,
accessToken: accessToken)
// Display the result!
drawImage(snapshot.image)
}
}
Directions CLI
MapboxDirectionsCLI
是一款命令行工具,可以遍历任意 JSON 格式的 Directions 或 Map Matching API 响应对象,并通过模型对象将其转换回 JSON 格式。这适用于各种场景,包括测试目的和设计更复杂的 API 响应处理管道。它作为一个 Swift 包提供。
使用 SPM 构建 MapboxDirectionsCLI
swift build
运行(如果尚未构建)并查看 MapboxDirectionsCLI
使用方法
swift run mapbox-directions-swift -h
有关更多信息,请参阅 MapboxDirectionsCLI 文档。