Skip to content

Commit

Permalink
Revisions based on PR feedback for MapView
Browse files Browse the repository at this point in the history
  • Loading branch information
Archdoog committed Dec 28, 2023
1 parent 10b26f3 commit 8db4709
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 36 deletions.
3 changes: 2 additions & 1 deletion Sources/MapLibreSwiftUI/Examples/Camera.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ struct CameraDirectManipulationPreview: View {
var body: some View {
MapView(styleURL: styleURL, camera: $camera)
.overlay(alignment: .bottom, content: {
Text("\(camera.coordinate.latitude), \(camera.coordinate.longitude) z \(camera.zoom ?? 0)")
Text("\(camera.coordinate.latitude), \(camera.coordinate.longitude) z \(camera.zoom)")
.padding()
.foregroundColor(.white)
.background(
Rectangle()
.foregroundColor(.black)
Expand Down
56 changes: 29 additions & 27 deletions Sources/MapLibreSwiftUI/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import SwiftUI
import InternalUtils
import MapLibre
import MapLibreSwiftDSL
import MapLibreSwiftUI

public struct MapView: UIViewRepresentable {

public private(set) var camera: Binding<MapViewCamera>?
public private(set) var camera: Binding<MapViewCamera>

public let styleSource: MapStyleSource
public let userLayers: [StyleLayerDefinition]
let styleSource: MapStyleSource
let userLayers: [StyleLayerDefinition]

public init(
styleURL: URL,
camera: Binding<MapViewCamera>? = nil,
camera: Binding<MapViewCamera> = .constant(.default()),
@MapViewContentBuilder _ makeMapContent: () -> [StyleLayerDefinition] = { [] }
) {
self.styleSource = .url(styleURL)
Expand All @@ -36,7 +35,7 @@ public struct MapView: UIViewRepresentable {
// Storage of variables as they were previously; these are snapshot
// every update cycle so we can avoid unnecessary updates
private var snapshotUserLayers: [StyleLayerDefinition] = []
var snapshotCamera: MapViewCamera?
private var snapshotCamera: MapViewCamera?

init(parent: MapView) {
self.parent = parent
Expand All @@ -59,13 +58,27 @@ public struct MapView: UIViewRepresentable {

public func mapView(_ mapView: MLNMapView, regionDidChangeAnimated animated: Bool) {
DispatchQueue.main.async {
self.parent.camera?.wrappedValue = .center(mapView.centerCoordinate,
zoom: mapView.zoomLevel)
self.parent.camera.wrappedValue = .center(mapView.centerCoordinate,
zoom: mapView.zoomLevel)
}
}

// MARK: - Coordinator API

func updateCamera(mapView: MLNMapView, camera: MapViewCamera, animated: Bool) {
guard camera != snapshotCamera else {
// No action - camera has not changed.
return
}

mapView.setCenter(camera.coordinate,
zoomLevel: camera.zoom,
direction: camera.course,
animated: animated)

snapshotCamera = camera
}

func updateLayers(mapView: MLNMapView) {
// TODO: Figure out how to selectively update layers when only specific props changed. New function in addition to makeMLNStyleLayer?

Expand Down Expand Up @@ -163,8 +176,10 @@ public struct MapView: UIViewRepresentable {
mapView.styleURL = styleURL
}

updateMapCamera(mapView, context: context, animated: false)

context.coordinator.updateCamera(mapView: mapView,
camera: camera.wrappedValue,
animated: false)

// TODO: Make this settable via a modifier
mapView.logoView.isHidden = true

Expand All @@ -180,26 +195,13 @@ public struct MapView: UIViewRepresentable {
// FIXME: This should be a more selective update
context.coordinator.updateStyleSource(styleSource, mapView: mapView)
context.coordinator.updateLayers(mapView: mapView)

// FIXME: This isn't exactly telling us if the *map* is loaded, and the docs for setCenter say it needs t obe.
let isStyleLoaded = mapView.style != nil

updateMapCamera(mapView, context: context, animated: isStyleLoaded)
}

private func updateMapCamera(_ mapView: MLNMapView, context: Context, animated: Bool) {
guard let newCamera = self.camera?.wrappedValue,
context.coordinator.snapshotCamera != newCamera else {
// Exit early - the camera has not changed.
return
}

mapView.setCenter(newCamera.coordinate,
zoomLevel: newCamera.zoom,
direction: newCamera.course,
animated: animated)

context.coordinator.snapshotCamera = newCamera
context.coordinator.updateCamera(mapView: mapView,
camera: camera.wrappedValue,
animated: isStyleLoaded)
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/MapLibreSwiftUI/Models/MapCamera/CameraState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public enum CameraState {
case centered

/// The camera is currently following a location provider.
case userLocation
case trackingUserLocation

/// Centered on a bounding box/rectangle.
case rect
Expand All @@ -24,7 +24,7 @@ extension CameraState: Equatable {

case (.centered, .centered):
return true
case (.userLocation, .userLocation):
case (.trackingUserLocation, .trackingUserLocation):
return true
case (.rect, .rect):
return true
Expand Down
12 changes: 6 additions & 6 deletions Sources/MapLibreSwiftUI/Models/MapCamera/MapViewCamera.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public struct MapViewCamera {
public var pitch: Double
public var course: CLLocationDirection

/// A backup camera centered at 0.0, 0.0. This is typically used as a backup,
/// A camera centered at 0.0, 0.0. This is typically used as a backup,
/// pre-load for an expected camera update (e.g. before a location provider produces
/// it's first location).
///
/// - Returns: The constructed MapViewCamera.
public static func backup() -> MapViewCamera {
public static func `default`() -> MapViewCamera {
return MapViewCamera(state: .centered,
coordinate: CLLocationCoordinate2D(latitude: 0, longitude: 0),
zoom: 10,
Expand Down Expand Up @@ -42,11 +42,11 @@ public struct MapViewCamera {
course: course)
}

public static func userLocation(_ location: CLLocation,
zoom: Double,
pitch: Double = 90.0) -> MapViewCamera {
public static func trackUserLocation(_ location: CLLocation,
zoom: Double,
pitch: Double = 90.0) -> MapViewCamera {

return MapViewCamera(state: .userLocation,
return MapViewCamera(state: .trackingUserLocation,
coordinate: location.coordinate,
zoom: zoom,
pitch: pitch,
Expand Down

0 comments on commit 8db4709

Please sign in to comment.