1
+ <p align =" center " >
2
+ <img src =" https://maplibre.org/img/maplibre-logo-big.svg " alt =" MapLibre Logo " >
3
+ </p >
4
+
1
5
# MapLibreSwiftUI
2
6
3
7
Swift DSLs for [ MapLibre Native] ( https://github.com/maplibre/maplibre-native ) , a free open-source renderer
4
8
for interactive vector maps, to enable better integration with SwiftUI and generally enable easier use of MapLibre.
5
9
6
10
![ A screen recording demonstrating the declarative SwiftUI DSL reacting to changes live] ( demo.gif )
7
11
8
- This package is a playground (read: not yet stable) to experiment with Swift DSLs and SwiftUI without constraints.
9
- As more people try this out with their own use cases, the community should eventuallly stabilize on a
10
- reasonably optimal DSL for working with MapLibre in Swift. The package name is currently MapLibreSwiftUI, but it's
11
- possible that the SwiftUI and DSL layers are separable.
12
-
13
- If successful, some version this project should eventually either get merged into MapLibre Native or at the least
14
- merged into the MapLibre organization more formally. It is being developed as a separate package initially so we
15
- can move fast without breaking anything important.
16
-
17
- ** NOTE: This currently only works on iOS, as that's the only architecture currently published in the dynamic framework.**
12
+ This package is a reimagining of the MapLibre API with a modern DSLs for SwiftUI.
13
+ The pre-1.0 status means only that we are not yet committed to API stability yet,
14
+ since we care deeply about finding the best way to express things for SwfitUI users.
15
+ The package is robust for the subset of the MapLibre iOS API that it supports.
16
+ Any breaking API changes will be reflected in release notes.
18
17
19
18
## Goals
20
19
21
- 1 . Primary: Make common use cases easy and make complicated ones possible
20
+ 1 . Primary: Make common use cases easy and [ make complicated ones possible] ( Sources/MapLibreSwiftUI/Examples/Other.swift )
22
21
* Easy integration of MapLibre into a modern SwiftUI app
23
- * Add markers and similar annotations
22
+ * Add [ markers] ( Sources/MapLibreSwiftUI/Examples/Gestures.swift ) , [ polylines] ( Sources/MapLibreSwiftUI/Examples/Polyline.swift ) and similar annotations
23
+ * Interaction with features through [ gestures] ( Sources/MapLibreSwiftUI/Examples/Gestures.swift )
24
24
* Clustering (common use case that's rather difficult for first timers)
25
- * Overlays
25
+ * [ Overlays]] ( Sources/MapLibreSwiftUI/Examples/ )
26
26
* Dynamic styling
27
- * Camera control / animation??
28
- * Navigation
27
+ * [ Camera control] ( Sources/MapLibreSwiftUI/Examples/Camera.swift )
28
+ * Turn-by-turn Navigation (see the showcase integrations below)
29
+ * Animation
29
30
2 . Prevent most common classes of mistakes that users make with the lower level APIs (ex: adding the same source twice)
30
31
3 . Deeper SwiftUI integration (ex: SwiftUI callout views)
31
32
@@ -44,28 +45,104 @@ Then, for each target add either the DSL (for just the DSL) or both (for the Swi
44
45
.product (name : " MapLibreSwiftUI" , package : " maplibre-swiftui-dsl-playground" ),
45
46
```
46
47
47
- Check out the (super basic) [ previews at the bottom of MapView.swift] ( Sources/MapLibreSwiftUI/MapView.swift )
48
- or more detailed [ Examples] ( Sources/MapLibreSwiftUI/Examples ) to see how it works in practice.
48
+ Then, you can use it in a SwiftUI view body like this:
49
+
50
+ ``` swift
51
+ import MapLibre
52
+ import MapLibreSwiftDSL
53
+ import SwiftUI
54
+ import CoreLocation
55
+
56
+ struct PolylineMapView : View {
57
+ // You'll need a MapLibre Style for this to work.
58
+ // You can use https://demotiles.maplibre.org/style.json for basic testing.
59
+ // For a list of commercially supported tile providers, check out https://wiki.openstreetmap.org/wiki/Vector_tiles#Providers.
60
+ // These providers all have their own "house styles" as well as custom styling.
61
+ // You can create your own style or modify others (subject to license restrictions) using https://maplibre.org/maputnik/.
62
+ let styleURL: URL
63
+
64
+ // Just a list of waypoints (ex: a route to follow)
65
+ let waypoints: [CLLocationCoordinate2D]
66
+
67
+ var body: some View {
68
+ MapView (styleURL : styleURL,
69
+ camera : .constant (.center (waypoints.first ! , zoom : 14 )))
70
+ {
71
+ // Define a data source.
72
+ // It will be automatically if a layer references it.
73
+ let polylineSource = ShapeSource (identifier : " polyline" ) {
74
+ MLNPolylineFeature (coordinates : waypoints)
75
+ }
76
+
77
+ // Add a polyline casing for a stroke effect
78
+ LineStyleLayer (identifier : " polyline-casing" , source : polylineSource)
79
+ .lineCap (.round )
80
+ .lineJoin (.round )
81
+ .lineColor (.white )
82
+ .lineWidth (interpolatedBy : .zoomLevel ,
83
+ curveType : .exponential ,
84
+ parameters : NSExpression (forConstantValue : 1.5 ),
85
+ stops : NSExpression (forConstantValue : [14 : 6 , 18 : 24 ]))
86
+
87
+ // Add an inner (blue) polyline
88
+ LineStyleLayer (identifier : " polyline-inner" , source : polylineSource)
89
+ .lineCap (.round )
90
+ .lineJoin (.round )
91
+ .lineColor (.systemBlue )
92
+ .lineWidth (interpolatedBy : .zoomLevel ,
93
+ curveType : .exponential ,
94
+ parameters : NSExpression (forConstantValue : 1.5 ),
95
+ stops : NSExpression (forConstantValue : [14 : 3 , 18 : 16 ]))
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Check out more [ Examples] ( Sources/MapLibreSwiftUI/Examples ) to go deeper.
49
102
50
- ## Common integrations
103
+ ** NOTE: This currently only works on iOS, as the dynamic framework doesn't yet include macOS.**
104
+
105
+ ## How can you help?
106
+
107
+ The first thing you can do is try it out!
108
+ Check out the [ Examples] ( Sources/MapLibreSwiftUI/Examples ) for inspiration,
109
+ swap it into your own SwiftUI app, or check out some showcase integrations for inspiration.
110
+ Putting it "through the paces" is the best way for us to converge on the "right" APIs as a community.
111
+ Your use case probably isn't supported today, in which case you can either open an issue or contribute a PR.
112
+
113
+ The code has a number of TODOs, most of which can be tackled by any intermediate Swift programmer.
114
+ The important issues should all be tracked in GitHub.
115
+ We also have a ` #maplibre-swiftui-compose-playground ` channel in the
116
+ [ OpenStreetMap US Slack] ( https://slack.openstreetmap.us/ ) .
117
+
118
+ The skeleton is already in place for several of the core concepts, including style layers and sources, but
119
+ these are incomplete. You can help by opening a PR that fills these in.
120
+ For example, if you wanted to fill out the API for the line style layer,
121
+ head over to [ the docs] ( https://maplibre.org/maplibre-native/ios/api/Classes/MGLLineStyleLayer.html )
122
+ and just start filling out the remaining properties and modifiers.
123
+
124
+ ## Showcase integrations
51
125
52
126
### Ferrostar
53
127
54
- [ Ferrostar] ( https://github.com/stadiamaps/ferrostar ) has a MapLibre UI module as part of its Swift Package
55
- which is already built on this!
128
+ [ Ferrostar] ( https://github.com/stadiamaps/ferrostar ) has a MapLibre UI module as part of its Swift Package.
129
+ That was actually the impetus for building this package,
130
+ and the core devs are eating their own dogfood.
56
131
See the [ SwiftUI customization] ( https://stadiamaps.github.io/ferrostar/swiftui-customization.html )
57
132
part of the Ferrostar user guide for details on how to customize the map.
58
133
59
134
### MapLibre Navigation iOS
60
135
61
- This package can help bridge the gap between MapLibre Navigation iOS and SwiftUI!
136
+ This package also helps to bridge the gap between MapLibre Navigation iOS and SwiftUI!
137
+ Thanks to developers from [ HudHud] ( https://hudhud.sa/en ) for their contributions which made this possible!
62
138
63
- Add the Swift Package froh Hudhud (https://github.com/HudHud-Maps /maplibre-navigation-ios.git ) to your Package.swift
64
- and add code like this:
139
+ Add the [ Swift Package] ( https://github.com/maplibre /maplibre-navigation-ios ) to your project.
140
+ Then add some code like this:
65
141
66
142
``` swift
67
143
import MapboxCoreNavigation
68
144
import MapboxNavigation
145
+ import MapLibreSwiftUI
69
146
70
147
extension NavigationViewController : MapViewHostViewController {
71
148
public typealias MapType = NavigationMapView
@@ -78,7 +155,7 @@ extension NavigationViewController: MapViewHostViewController {
78
155
@ViewBuilder
79
156
var mapView: some View {
80
157
MapView< NavigationViewController> (makeViewController : NavigationViewController (dayStyleURL : self .styleURL ), styleURL : self .styleURL , camera : self .$mapStore.camera ) {
81
-
158
+ // TODO: Your customizations here; add more layers or whatever you like!
82
159
}
83
160
.unsafeMapViewControllerModifier { navigationViewController in
84
161
navigationViewController.delegate = self .mapStore
@@ -96,52 +173,3 @@ var mapView: some View {
96
173
.cameraModifierDisabled (self .route != nil )
97
174
}
98
175
```
99
-
100
- ## Developer Quick Start
101
-
102
- This project is a standard Swift package.
103
- The only special thing you might need besides Xcode is [ ` swiftformat ` ] ( https://github.com/nicklockwood/SwiftFormat ) .
104
- We use it to automatically handle basic formatting and to linting
105
- so the code has a standard style.
106
-
107
- Check out the swiftformat [ Install Guide] ( https://github.com/nicklockwood/SwiftFormat?tab=readme-ov-file#how-do-i-install-it )
108
- to add swiftformat to your machine.
109
- Once installed, you can autoformat code using the command:
110
-
111
- ``` sh
112
- swiftformat .
113
- ```
114
-
115
- Swiftformat can occasionally poorly resolve a formatting issue (e.g. when you've already line-broken a large comment).
116
- Issues like this are typically easy to manually correct.
117
-
118
- ## Structure
119
-
120
- This package is structured into a few targets. ` InternalUtils ` is pretty much what it says. ` MapLibreSwiftDSL ` and
121
- ` MapLibreSwiftUI ` are published products, and make up the bulk of the project. Finally, ` Examples ` is a collection of
122
- SwiftUI previews.
123
-
124
- The DSL provides a more Swift-y layer on top of the lower level MapLibre APIs, and features a number of
125
- result builders which enable more modern expressive APIs.
126
-
127
- The SwiftUI layer publishes a SwiftUI view with the end goal of being a universal view that can be adapted to a wide
128
- variety of use cases, much like MapKit's SwiftUI views.
129
-
130
- The ` Examples ` should serve as a rough indication of development progress. While much of the code in the UI layer
131
- isn't formally tested, this acts as our test, and for all intents and purposes, we're following a practical variant of
132
- TDD as we build out functionality.
133
-
134
- ## How can you help?
135
-
136
- The first thing you can do is try out the library! Check out the detailed [ Examples] ( Sources/MapLibreSwiftUI/Examples )
137
- for inspiration. Putting it "through the paces" is the best way for us to converge on the "right" APIs as a community.
138
- Your use case probably isn't supported today, in which case you can either open an issue or contribute a PR.
139
-
140
- The code has a number of TODOs, most of which can be tackled by any intermediate Swift programmer. The important
141
- issues should all be tracked in GitHub. DISCUSS comments (should migrate to GitHub issues/discussions) are deeper
142
- questions. Input welcome.
143
-
144
- The skeleton is already in place for several of the core concepts, including style layers and sources, but
145
- these are incomplete. You can help by opening a PR that fills these in. For example, if you wanted to fill out the
146
- API for the line style layer, head over to [ the docs] ( https://maplibre.org/maplibre-native/ios/api/Classes/MGLLineStyleLayer.html )
147
- and get to work filling out the remaining properties and modifiers.
0 commit comments