Skip to content

Commit ce0bf6e

Browse files
authored
Feat/user location style (#112)
* Feat: custom annotation style * Feat: custom annotation style * Feat: revised modifier name
1 parent 210b632 commit ce0bf6e

File tree

7 files changed

+191
-4
lines changed

7 files changed

+191
-4
lines changed

Package.resolved

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/MapLibreSwiftUI/Examples/User Location.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import CoreLocation
2+
import MapLibre
23
import MapLibreSwiftDSL
34
import SwiftUI
45

@@ -35,3 +36,55 @@ private let locationManager = StaticLocationManager(initialLocation: CLLocation(
3536
}
3637
.ignoresSafeArea(.all)
3738
}
39+
40+
#Preview("Track user location with custom annotation") {
41+
MapView(
42+
styleURL: demoTilesURL,
43+
camera: .constant(.trackUserLocation(zoom: 4, pitch: 45)),
44+
locationManager: locationManager
45+
)
46+
.mapViewContentInset(.init(top: 450, left: 0, bottom: 0, right: 0))
47+
.mapControls {
48+
LogoView()
49+
}
50+
.mapUserAnnotationStyle(
51+
MapUserAnnotationStyle(
52+
approximateHaloBorderColor: .orange,
53+
approximateHaloBorderWidth: 50,
54+
approximateHaloFillColor: .orange,
55+
approximateHaloOpacity: 0.5,
56+
haloFillColor: .orange,
57+
puckArrowFillColor: .orange,
58+
puckFillColor: .orange,
59+
puckShadowColor: .white,
60+
puckShadowOpacity: 0.5
61+
)
62+
)
63+
.ignoresSafeArea(.all)
64+
}
65+
66+
#Preview("Track user location with course with custom annotation") {
67+
MapView(
68+
styleURL: demoTilesURL,
69+
camera: .constant(.trackUserLocationWithCourse(zoom: 4, pitch: 45)),
70+
locationManager: locationManager
71+
)
72+
.mapViewContentInset(.init(top: 450, left: 0, bottom: 0, right: 0))
73+
.mapControls {
74+
LogoView()
75+
}
76+
.mapUserAnnotationStyle(
77+
MapUserAnnotationStyle(
78+
approximateHaloBorderColor: .orange,
79+
approximateHaloBorderWidth: 50,
80+
approximateHaloFillColor: .orange,
81+
approximateHaloOpacity: 0.5,
82+
haloFillColor: .orange,
83+
puckArrowFillColor: .orange,
84+
puckFillColor: .orange,
85+
puckShadowColor: .white,
86+
puckShadowOpacity: 0.5
87+
)
88+
)
89+
.ignoresSafeArea(.all)
90+
}

Sources/MapLibreSwiftUI/MapView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public struct MapView<T: MapViewHostViewController>: UIViewControllerRepresentab
3131
let userLayers: [StyleLayerDefinition]
3232

3333
var gestures = [MapGesture]()
34+
var annotationStyle = MLNUserLocationAnnotationViewStyle()
3435

3536
var onStyleLoaded: ((MLNStyle) -> Void)?
3637
var onUserTrackingModeChanged: ((MLNUserTrackingMode, Bool) -> Void)?

Sources/MapLibreSwiftUI/MapViewCoordinator.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ MLNMapViewDelegate {
432432
cameraUpdateTask = nil
433433
}
434434

435+
@MainActor
436+
public func mapView(styleForDefaultUserLocationAnnotationView _: MLNMapView) -> MLNUserLocationAnnotationViewStyle {
437+
parent.annotationStyle
438+
}
439+
435440
@MainActor
436441
public func mapView(_ mapView: MLNMapView, regionIsChangingWith reason: MLNCameraChangeReason) {
437442
if proxyUpdateMode == .realtime {

Sources/MapLibreSwiftUI/MapViewModifiers.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,16 @@ public extension MapView {
141141
return result
142142
}
143143

144+
/// Customize the user location annotation style
145+
///
146+
/// - Parameter annotationStyle: The customized annotation style.
147+
/// - Returns: The modified MapView
148+
func mapUserAnnotationStyle(_ annotationStyle: MapUserAnnotationStyle) -> Self {
149+
var newMapView = self
150+
newMapView.annotationStyle = annotationStyle.value
151+
return newMapView
152+
}
153+
144154
/// The view modifier recieves an instance of `MapViewProxy`, which contains read only information about the current
145155
/// state of the
146156
/// `MapView` such as its bounds, center and insets.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import MapLibre
2+
import SwiftUI
3+
4+
/// An abstraction of the [MLNUserLocationAnnotationViewStyle](https://maplibre.org/maplibre-native/ios/latest/documentation/maplibre/mlnuserlocationannotationviewstyle/)
5+
public struct MapUserAnnotationStyle {
6+
/// The halo border color for the approximate view.
7+
var approximateHaloBorderColor: Color
8+
9+
/// The halo border width for the approximate view. The default value of this property is equal to 2.0
10+
var approximateHaloBorderWidth: CGFloat
11+
12+
/// The halo fill color for the approximate view.
13+
var approximateHaloFillColor: Color
14+
15+
/// The halo opacity for the approximate view. Set any value between 0.0 and 1.0 The default value of this property
16+
/// is equal to 0.15
17+
var approximateHaloOpacity: CGFloat
18+
19+
/// The fill color for the puck view.
20+
var haloFillColor: Color
21+
22+
/// The fill color for the arrow puck.
23+
var puckArrowFillColor: Color
24+
25+
/// The fill color for the puck view.
26+
var puckFillColor: Color
27+
28+
/// The shadow color for the puck view.
29+
var puckShadowColor: Color
30+
31+
/// The shadow opacity for the puck view. Set any value between 0.0 and 1.0. The default value of this property is
32+
/// equal to 0.25
33+
var puckShadowOpacity: CGFloat
34+
35+
/// Create a custom user location annotation style.
36+
///
37+
/// - Parameters:
38+
/// - approximateHaloBorderColor: The halo border color for the approximate view.
39+
/// - approximateHaloBorderWidth: The halo border width for the approximate view. The default value of this
40+
/// property is equal to 2.0
41+
/// - approximateHaloFillColor: The halo fill color for the approximate view.
42+
/// - approximateHaloOpacity: The halo opacity for the approximate view. Set any value between 0.0 and 1.0 The
43+
/// default value of this property is equal to 0.15
44+
/// - haloFillColor: The fill color for the puck view.
45+
/// - puckArrowFillColor: The fill color for the arrow puck.
46+
/// - puckFillColor: The fill color for the puck view.
47+
/// - puckShadowColor: The shadow color for the puck view.
48+
/// - puckShadowOpacity: The shadow opacity for the puck view. Set any value between 0.0 and 1.0. The default
49+
/// value of this property is equal to 0.25
50+
public init(
51+
approximateHaloBorderColor: Color = .white,
52+
approximateHaloBorderWidth: CGFloat = 2.0,
53+
approximateHaloFillColor: Color = .primary,
54+
approximateHaloOpacity: CGFloat = 0.15,
55+
haloFillColor: Color = .primary,
56+
puckArrowFillColor: Color = .primary,
57+
puckFillColor: Color = .white,
58+
puckShadowColor: Color = .black,
59+
puckShadowOpacity: CGFloat = 0.25
60+
) {
61+
self.approximateHaloBorderColor = approximateHaloBorderColor
62+
self.approximateHaloBorderWidth = approximateHaloBorderWidth
63+
self.approximateHaloFillColor = approximateHaloFillColor
64+
self.approximateHaloOpacity = approximateHaloOpacity
65+
self.haloFillColor = haloFillColor
66+
self.puckArrowFillColor = puckArrowFillColor
67+
self.puckFillColor = puckFillColor
68+
self.puckShadowColor = puckShadowColor
69+
self.puckShadowOpacity = puckShadowOpacity
70+
}
71+
}
72+
73+
extension MapUserAnnotationStyle {
74+
/// The MLN value used on the underlying MLNMapView
75+
var value: MLNUserLocationAnnotationViewStyle {
76+
let value = MLNUserLocationAnnotationViewStyle()
77+
value.approximateHaloBorderColor = UIColor(approximateHaloBorderColor)
78+
value.approximateHaloBorderWidth = approximateHaloBorderWidth
79+
value.approximateHaloFillColor = UIColor(approximateHaloFillColor)
80+
value.approximateHaloOpacity = approximateHaloOpacity
81+
value.haloFillColor = UIColor(haloFillColor)
82+
value.puckArrowFillColor = UIColor(puckArrowFillColor)
83+
value.puckFillColor = UIColor(puckFillColor)
84+
value.puckShadowColor = UIColor(puckShadowColor)
85+
value.puckShadowOpacity = puckShadowOpacity
86+
return value
87+
}
88+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Testing
2+
@testable import MapLibreSwiftUI
3+
4+
struct MapUserAnnotationStyleTest {
5+
@Test("The MapUserAnnotationStyle values are properly assigned")
6+
func values() async throws {
7+
let custom = MapUserAnnotationStyle(
8+
approximateHaloBorderColor: .orange,
9+
approximateHaloBorderWidth: 50,
10+
approximateHaloFillColor: .blue,
11+
approximateHaloOpacity: 0.5,
12+
haloFillColor: .green,
13+
puckArrowFillColor: .yellow,
14+
puckFillColor: .red,
15+
puckShadowColor: .pink,
16+
puckShadowOpacity: 0.1
17+
)
18+
let mlnValue = custom.value
19+
20+
#expect(mlnValue.approximateHaloBorderColor == .systemOrange)
21+
#expect(mlnValue.approximateHaloBorderWidth == 50)
22+
#expect(mlnValue.approximateHaloFillColor == .systemBlue)
23+
#expect(mlnValue.approximateHaloOpacity == 0.5)
24+
#expect(mlnValue.haloFillColor == .systemGreen)
25+
#expect(mlnValue.puckArrowFillColor == .systemYellow)
26+
#expect(mlnValue.puckFillColor == .systemRed)
27+
#expect(mlnValue.puckShadowColor == .systemPink)
28+
#expect(mlnValue.puckShadowOpacity == 0.1)
29+
}
30+
}

0 commit comments

Comments
 (0)