Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions Sources/MapLibreSwiftUI/Examples/User Location.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CoreLocation
import MapLibre
import MapLibreSwiftDSL
import SwiftUI

Expand Down Expand Up @@ -35,3 +36,55 @@ private let locationManager = StaticLocationManager(initialLocation: CLLocation(
}
.ignoresSafeArea(.all)
}

#Preview("Track user location with custom annotation") {
MapView(
styleURL: demoTilesURL,
camera: .constant(.trackUserLocation(zoom: 4, pitch: 45)),
locationManager: locationManager
)
.mapViewContentInset(.init(top: 450, left: 0, bottom: 0, right: 0))
.mapControls {
LogoView()
}
.mapUserAnnotationStyle(
MapUserAnnotationStyle(
approximateHaloBorderColor: .orange,
approximateHaloBorderWidth: 50,
approximateHaloFillColor: .orange,
approximateHaloOpacity: 0.5,
haloFillColor: .orange,
puckArrowFillColor: .orange,
puckFillColor: .orange,
puckShadowColor: .white,
puckShadowOpacity: 0.5
)
)
.ignoresSafeArea(.all)
}

#Preview("Track user location with course with custom annotation") {
MapView(
styleURL: demoTilesURL,
camera: .constant(.trackUserLocationWithCourse(zoom: 4, pitch: 45)),
locationManager: locationManager
)
.mapViewContentInset(.init(top: 450, left: 0, bottom: 0, right: 0))
.mapControls {
LogoView()
}
.mapUserAnnotationStyle(
MapUserAnnotationStyle(
approximateHaloBorderColor: .orange,
approximateHaloBorderWidth: 50,
approximateHaloFillColor: .orange,
approximateHaloOpacity: 0.5,
haloFillColor: .orange,
puckArrowFillColor: .orange,
puckFillColor: .orange,
puckShadowColor: .white,
puckShadowOpacity: 0.5
)
)
.ignoresSafeArea(.all)
}
1 change: 1 addition & 0 deletions Sources/MapLibreSwiftUI/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public struct MapView<T: MapViewHostViewController>: UIViewControllerRepresentab
let userLayers: [StyleLayerDefinition]

var gestures = [MapGesture]()
var annotationStyle = MLNUserLocationAnnotationViewStyle()

var onStyleLoaded: ((MLNStyle) -> Void)?
var onUserTrackingModeChanged: ((MLNUserTrackingMode, Bool) -> Void)?
Expand Down
5 changes: 5 additions & 0 deletions Sources/MapLibreSwiftUI/MapViewCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,11 @@ MLNMapViewDelegate {
cameraUpdateTask = nil
}

@MainActor
public func mapView(styleForDefaultUserLocationAnnotationView _: MLNMapView) -> MLNUserLocationAnnotationViewStyle {
parent.annotationStyle
}

@MainActor
public func mapView(_ mapView: MLNMapView, regionIsChangingWith reason: MLNCameraChangeReason) {
if proxyUpdateMode == .realtime {
Expand Down
10 changes: 10 additions & 0 deletions Sources/MapLibreSwiftUI/MapViewModifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ public extension MapView {
return result
}

/// Customize the user location annotation style
///
/// - Parameter annotationStyle: The customized annotation style.
/// - Returns: The modified MapView
func mapUserAnnotationStyle(_ annotationStyle: MapUserAnnotationStyle) -> Self {
var newMapView = self
newMapView.annotationStyle = annotationStyle.value
return newMapView
}

/// The view modifier recieves an instance of `MapViewProxy`, which contains read only information about the current
/// state of the
/// `MapView` such as its bounds, center and insets.
Expand Down
88 changes: 88 additions & 0 deletions Sources/MapLibreSwiftUI/Models/MapUserAnnotationStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import MapLibre
import SwiftUI

/// An abstraction of the [MLNUserLocationAnnotationViewStyle](https://maplibre.org/maplibre-native/ios/latest/documentation/maplibre/mlnuserlocationannotationviewstyle/)
public struct MapUserAnnotationStyle {
/// The halo border color for the approximate view.
var approximateHaloBorderColor: Color

/// The halo border width for the approximate view. The default value of this property is equal to 2.0
var approximateHaloBorderWidth: CGFloat

/// The halo fill color for the approximate view.
var approximateHaloFillColor: Color

/// The halo opacity for the approximate view. Set any value between 0.0 and 1.0 The default value of this property
/// is equal to 0.15
var approximateHaloOpacity: CGFloat

/// The fill color for the puck view.
var haloFillColor: Color

/// The fill color for the arrow puck.
var puckArrowFillColor: Color

/// The fill color for the puck view.
var puckFillColor: Color

/// The shadow color for the puck view.
var puckShadowColor: Color

/// The shadow opacity for the puck view. Set any value between 0.0 and 1.0. The default value of this property is
/// equal to 0.25
var puckShadowOpacity: CGFloat

/// Create a custom user location annotation style.
///
/// - Parameters:
/// - approximateHaloBorderColor: The halo border color for the approximate view.
/// - approximateHaloBorderWidth: The halo border width for the approximate view. The default value of this
/// property is equal to 2.0
/// - approximateHaloFillColor: The halo fill color for the approximate view.
/// - approximateHaloOpacity: The halo opacity for the approximate view. Set any value between 0.0 and 1.0 The
/// default value of this property is equal to 0.15
/// - haloFillColor: The fill color for the puck view.
/// - puckArrowFillColor: The fill color for the arrow puck.
/// - puckFillColor: The fill color for the puck view.
/// - puckShadowColor: The shadow color for the puck view.
/// - puckShadowOpacity: The shadow opacity for the puck view. Set any value between 0.0 and 1.0. The default
/// value of this property is equal to 0.25
public init(
approximateHaloBorderColor: Color = .white,
approximateHaloBorderWidth: CGFloat = 2.0,
approximateHaloFillColor: Color = .primary,
approximateHaloOpacity: CGFloat = 0.15,
haloFillColor: Color = .primary,
puckArrowFillColor: Color = .primary,
puckFillColor: Color = .white,
puckShadowColor: Color = .black,
puckShadowOpacity: CGFloat = 0.25
) {
self.approximateHaloBorderColor = approximateHaloBorderColor
self.approximateHaloBorderWidth = approximateHaloBorderWidth
self.approximateHaloFillColor = approximateHaloFillColor
self.approximateHaloOpacity = approximateHaloOpacity
self.haloFillColor = haloFillColor
self.puckArrowFillColor = puckArrowFillColor
self.puckFillColor = puckFillColor
self.puckShadowColor = puckShadowColor
self.puckShadowOpacity = puckShadowOpacity
}
}

extension MapUserAnnotationStyle {
/// The MLN value used on the underlying MLNMapView
var value: MLNUserLocationAnnotationViewStyle {
let value = MLNUserLocationAnnotationViewStyle()
value.approximateHaloBorderColor = UIColor(approximateHaloBorderColor)
value.approximateHaloBorderWidth = approximateHaloBorderWidth
value.approximateHaloFillColor = UIColor(approximateHaloFillColor)
value.approximateHaloOpacity = approximateHaloOpacity
value.haloFillColor = UIColor(haloFillColor)
value.puckArrowFillColor = UIColor(puckArrowFillColor)
value.puckFillColor = UIColor(puckFillColor)
value.puckShadowColor = UIColor(puckShadowColor)
value.puckShadowOpacity = puckShadowOpacity
return value
}
}
30 changes: 30 additions & 0 deletions Tests/MapLibreSwiftUITests/Models/MapUserAnnotationStyleTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Testing
@testable import MapLibreSwiftUI

struct MapUserAnnotationStyleTest {
@Test("The MapUserAnnotationStyle values are properly assigned")
func values() async throws {
let custom = MapUserAnnotationStyle(
approximateHaloBorderColor: .orange,
approximateHaloBorderWidth: 50,
approximateHaloFillColor: .blue,
approximateHaloOpacity: 0.5,
haloFillColor: .green,
puckArrowFillColor: .yellow,
puckFillColor: .red,
puckShadowColor: .pink,
puckShadowOpacity: 0.1
)
let mlnValue = custom.value

#expect(mlnValue.approximateHaloBorderColor == .systemOrange)
#expect(mlnValue.approximateHaloBorderWidth == 50)
#expect(mlnValue.approximateHaloFillColor == .systemBlue)
#expect(mlnValue.approximateHaloOpacity == 0.5)
#expect(mlnValue.haloFillColor == .systemGreen)
#expect(mlnValue.puckArrowFillColor == .systemYellow)
#expect(mlnValue.puckFillColor == .systemRed)
#expect(mlnValue.puckShadowColor == .systemPink)
#expect(mlnValue.puckShadowOpacity == 0.1)
}
}
Loading