用于 MapLibre Native 的 Swift DSL,MapLibre Native 是一个免费的开源交互式矢量地图渲染器,旨在更好地与 SwiftUI 集成,并通常使 MapLibre 更易于使用。
注意:此软件包已从 Stadia Maps 迁移到 MapLibre 组织 🎉 如果您之前安装过此软件包,请参阅 CHANGELOG
,了解确保 Xcode 正常运行的步骤。
此软件包是对 MapLibre API 的重新构想,采用适用于 SwiftUI 的现代 DSL。 1.0 之前的状态意味着我们尚未承诺 API 的稳定性,因为我们非常关心为 SwiftUI 用户找到表达事物的最佳方式。 该软件包对于其支持的 MapLibre iOS API 子集来说是稳健的。 任何破坏性的 API 更改都将反映在发行说明中。
如果您正在使用 Xcode 项目构建应用程序,则添加软件包依赖项的最简单方法是在“文件”菜单中。 使用存储库 URL 搜索软件包:https://github.com/maplibre/swiftui-dsl
。
将以下内容添加到 Package.swift
的主要依赖项部分。
.package(url: "https://github.com/maplibre/swiftui-dsl", branch: "main"),
然后,对于每个目标,添加 DSL(仅用于 DSL)或两者都添加(用于 SwiftUI 视图)
.product(name: "MapLibreSwiftDSL", package: "swiftui-dsl"),
.product(name: "MapLibreSwiftUI", package: "swiftui-dsl"),
然后,您可以像这样在 SwiftUI 视图主体中使用它
import MapLibre
import MapLibreSwiftDSL
import SwiftUI
import CoreLocation
struct PolylineMapView: View {
// You'll need a MapLibre Style for this to work.
// You can use https://demotiles.maplibre.org/style.json for basic testing.
// For a list of commercially supported tile providers, check out https://wiki.openstreetmap.org/wiki/Vector_tiles#Providers.
// These providers all have their own "house styles" as well as custom styling.
// You can create your own style or modify others (subject to license restrictions) using https://maplibre.org/maputnik/.
let styleURL: URL
// Just a list of waypoints (ex: a route to follow)
let waypoints: [CLLocationCoordinate2D]
var body: some View {
MapView(styleURL: styleURL,
camera: .constant(.center(waypoints.first!, zoom: 14)))
{
// Define a data source.
// It will be automatically if a layer references it.
let polylineSource = ShapeSource(identifier: "polyline") {
MLNPolylineFeature(coordinates: waypoints)
}
// Add a polyline casing for a stroke effect
LineStyleLayer(identifier: "polyline-casing", source: polylineSource)
.lineCap(.round)
.lineJoin(.round)
.lineColor(.white)
.lineWidth(interpolatedBy: .zoomLevel,
curveType: .exponential,
parameters: NSExpression(forConstantValue: 1.5),
stops: NSExpression(forConstantValue: [14: 6, 18: 24]))
// Add an inner (blue) polyline
LineStyleLayer(identifier: "polyline-inner", source: polylineSource)
.lineCap(.round)
.lineJoin(.round)
.lineColor(.systemBlue)
.lineWidth(interpolatedBy: .zoomLevel,
curveType: .exponential,
parameters: NSExpression(forConstantValue: 1.5),
stops: NSExpression(forConstantValue: [14: 3, 18: 16]))
}
}
}
查看更多示例以深入了解。
注意:目前这仅适用于 iOS,因为动态框架尚未包含 macOS。
您可以做的第一件事是尝试一下! 查看 示例 以获取灵感,将其切换到您自己的 SwiftUI 应用程序中,或者查看一些展示集成以获取灵感。 对其进行 "全面测试" 是我们作为社区达成 "正确" API 的最佳方式。 您的用例可能目前不受支持,在这种情况下,您可以提出问题或贡献 PR。
代码中有许多 TODO,其中大多数可以由任何中级 Swift 程序员解决。 重要的 Issues 应该都在 GitHub 中跟踪。 我们还在 OpenStreetMap US Slack 中有一个 #maplibre-swiftui-compose-playground
频道。
几个核心概念(包括样式图层和源)的框架已经到位,但这些是不完整的。 您可以通过打开 PR 来填充这些框架来提供帮助。 例如,如果您想填写线条样式图层的 API,请前往 文档 并开始填写剩余的属性和修改器。
Ferrostar 在其 Swift 软件包中包含一个 MapLibre UI 模块。 这实际上是构建此软件包的动力,并且核心开发人员正在自食其果。 请参阅 Ferrostar 用户指南的 SwiftUI 自定义 部分,了解如何自定义地图的详细信息。
该软件包还有助于弥合 MapLibre Navigation iOS 和 SwiftUI 之间的差距! 感谢来自 HudHud 的开发人员为此做出的贡献!
将 Swift 软件包 添加到您的项目中。 然后添加如下代码
import MapboxCoreNavigation
import MapboxNavigation
import MapLibreSwiftUI
extension NavigationViewController: MapViewHostViewController {
public typealias MapType = NavigationMapView
}
@State var route: Route?
@State var navigationInProgress: Bool = false
@ViewBuilder
var mapView: some View {
MapView<NavigationViewController>(makeViewController: NavigationViewController(dayStyleURL: self.styleURL), styleURL: self.styleURL, camera: self.$mapStore.camera) {
// TODO: Your customizations here; add more layers or whatever you like!
}
.unsafeMapViewControllerModifier { navigationViewController in
navigationViewController.delegate = self.mapStore
if let route = self.route, self.navigationInProgress == false {
let locationManager = SimulatedLocationManager(route: route)
navigationViewController.startNavigation(with: route, locationManager: locationManager)
self.navigationInProgress = true
} else if self.route == nil, self.navigationInProgress == true {
navigationViewController.endNavigation()
self.navigationInProgress = false
}
navigationViewController.mapView.showsUserLocation = self.showUserLocation && self.mapStore.streetView == .disabled
}
.cameraModifierDisabled(self.route != nil)
}