-
Notifications
You must be signed in to change notification settings - Fork 313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Navigation camera viewport API. #2826
Merged
Merged
Changes from 32 commits
Commits
Show all changes
72 commits
Select commit
Hold shift + click to select a range
ff65ef0
Add initial version of Navigation Viewport Camera API.
MaximAlien 98254fc
Replace `NavigationCameraStateObserver` with NSNotification.
MaximAlien 8d75a02
Update only user puck when arriving to highlighted building.
MaximAlien 8d91b36
Remove `NavigationMapViewCourseTrackingDelegate`.
MaximAlien 7850866
Update `CustomViewController` to new camera behavior.
MaximAlien 6766e5d
Add ability to cancel pending camera transitions.
MaximAlien cb2147c
Add array extensions required for transitions.
MaximAlien d576504
Add basic implementation of transitions functionality.
MaximAlien e32c678
Simplify transition completion.
MaximAlien 35ff55e
Fix issue related to incorrect camera positioning right before maneuver.
MaximAlien 91786ec
Improve `UserCourseView` handling during camera transitions.
MaximAlien 2c0fbf8
Refactor `NavigationViewportDataSource` to simplify `CameraOptions` c…
MaximAlien 4007e68
Add `NavigationCameraDebugView` to be able to debug viewport related …
MaximAlien fab68e9
Improve `UserCourseView` updates when running long animations. Improv…
MaximAlien 3caf811
Make frame by frame `UserCourseView` location updates default.
MaximAlien 7a60c97
Simplify `NavigationCameraStateTransition`.
MaximAlien 0956c59
Fix crash in `CameraView` in case if location is invalid.
MaximAlien 8ea2d04
Improve viewport padding related issues.
MaximAlien d1d7315
Improve notifications handling in `NavigationCameraDebugView`.
MaximAlien 24c5a3e
Rename method.
MaximAlien d6b60fb
Introduce `ViewportDataSourceType` to be able to control what locatio…
MaximAlien 203601c
Integrate Mapbox Maps CameraView and CameraAnimator. (#2886)
MaximAlien f26520e
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 9c02e73
Improve indentation.
MaximAlien ded2563
Add ability to use `PassiveLocationManager` on CarPlay.
MaximAlien a06b8eb
Improve camera viewport related issues on iOS and CarPlay.
MaximAlien 81812a2
Add more debugging instruments.
MaximAlien 7b2ed48
Minor improvements.
MaximAlien 876093b
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 41093db
Resolve outstanding conflicts in CocoaPodsTest.
MaximAlien aad725f
Minor properties renaming.
MaximAlien f2d5268
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien d0497d8
Set initial coordinate for active guidance navigation on CarPlay.
MaximAlien 38d9827
Update changelog and jazzy docs.
MaximAlien e32f4dd
Minor improvements in camera transitions.
MaximAlien f59cb67
Fix camera related issues in `CustomViewController`.
MaximAlien fdc8724
Make `NavigationCameraDebugView` part of MapboxNavigation to simplify…
MaximAlien 8a28635
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien c513aaf
Update jazzy docs.
MaximAlien cfb8516
Add more information to navigation camera debugging view.
MaximAlien c9d698e
Further improvements to make debugging easier.
MaximAlien 2e2a348
Fix padding in active guidance for CarPlay.
MaximAlien 6ad741f
Make navigationViewportDataSource weak.
MaximAlien 5714845
Fix issues related to fitting camera on CarPlay while previewing rout…
MaximAlien 0e41bac
Fix issue related to switching between overview and following modes o…
MaximAlien 0f462de
Use non-zero padding in overview mode on CarPlay.
MaximAlien cd4aad2
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 6e5dca7
Remove the ability to control visibility of `NavigationCameraDebugVie…
MaximAlien 8340599
Remove custom implementations of navigation camera as they were moved…
MaximAlien a019037
Improve `PassiveLocationDataSource` management.
MaximAlien cd82049
Fix issue, which was causing incorrect position of camera on CarPlay …
MaximAlien 4410a3b
Improve NavigationCameraDebugView drawing.
MaximAlien 1edae74
Fix issue, which was causing incorrect camera behavior on CarPlay in …
MaximAlien 1360d07
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 3cc94c5
Fix memory leak in `NavigationMapView`.
MaximAlien 77e68c8
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 3de06ff
Address code review feedback.
MaximAlien 6900f49
Remove excessive `CLLocation` extension.
MaximAlien 4e47417
Address code review feedback.
MaximAlien 56cd738
Update `FrameIntervalOptions`.
MaximAlien 8bb685d
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 578b705
Update changelog.
MaximAlien c4ae428
Disable debugging view, improve comments.
MaximAlien 1f60266
Fix issue related to incorrect `UserCourseView` bearing.
MaximAlien 242ee49
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien 465fb2a
Add `defaultAltitude`, which is used as part of initial `NavigationCa…
MaximAlien 3fff0f1
Remove unused `CLLocationDegrees` extension.
MaximAlien 41d0db0
Add two new public properties: `useBearingSmoothing` and `maxBearingA…
MaximAlien dc51870
Change default value for `maxBearingAngleDiffWhenSmoothing`.
MaximAlien c4ee83a
Add `distanceToFrameAfterManeuver` public property.
MaximAlien 04694a9
Simplify `NavigationViewportDataSource` public APIs and improve docum…
MaximAlien 371729d
Merge branch 'release-v2.0' into maxim/camera-viewport-api
MaximAlien File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import MapboxMaps | ||
import MapboxNavigation | ||
|
||
class CustomCameraStateTransition: CameraStateTransition { | ||
|
||
weak var mapView: MapView? | ||
|
||
required init(_ mapView: MapView) { | ||
self.mapView = mapView | ||
} | ||
|
||
func transitionToFollowing(_ cameraOptions: CameraOptions, completion: @escaping (() -> Void)) { | ||
mapView?.cameraManager.setCamera(to: cameraOptions, | ||
animated: true, | ||
duration: 0.5, | ||
completion: { _ in | ||
completion() | ||
}) | ||
} | ||
|
||
func transitionToOverview(_ cameraOptions: CameraOptions, completion: @escaping (() -> Void)) { | ||
mapView?.cameraManager.setCamera(to: cameraOptions, | ||
animated: true, | ||
duration: 0.5, | ||
completion: { _ in | ||
completion() | ||
}) | ||
} | ||
|
||
func updateForFollowing(_ cameraOptions: CameraOptions) { | ||
mapView?.cameraManager.setCamera(to: cameraOptions, | ||
animated: true, | ||
duration: 0.5, | ||
completion: nil) | ||
} | ||
|
||
func updateForOverview(_ cameraOptions: CameraOptions) { | ||
mapView?.cameraManager.setCamera(to: cameraOptions, | ||
animated: true, | ||
duration: 0.5, | ||
completion: nil) | ||
} | ||
|
||
func cancelPendingTransition() { | ||
mapView?.cameraManager.cancelTransitions() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import MapboxMaps | ||
import MapboxNavigation | ||
import MapboxCoreNavigation | ||
|
||
class CustomViewportDataSource: ViewportDataSource { | ||
|
||
public var delegate: ViewportDataSourceDelegate? | ||
|
||
public var followingMobileCamera: CameraOptions = CameraOptions() | ||
|
||
public var followingHeadUnitCamera: CameraOptions = CameraOptions() | ||
|
||
public var overviewMobileCamera: CameraOptions = CameraOptions() | ||
|
||
public var overviewHeadUnitCamera: CameraOptions = CameraOptions() | ||
|
||
weak var mapView: MapView? | ||
|
||
// MARK: - Initializer methods | ||
|
||
public required init(_ mapView: MapView) { | ||
self.mapView = mapView | ||
self.mapView?.locationManager.addLocationConsumer(newConsumer: self) | ||
|
||
subscribeForNotifications() | ||
} | ||
|
||
deinit { | ||
unsubscribeFromNotifications() | ||
} | ||
|
||
// MARK: - Notifications observer methods | ||
|
||
func subscribeForNotifications() { | ||
NotificationCenter.default.addObserver(self, | ||
selector: #selector(progressDidChange(_:)), | ||
name: .routeControllerProgressDidChange, | ||
object: nil) | ||
} | ||
|
||
func unsubscribeFromNotifications() { | ||
NotificationCenter.default.removeObserver(self, | ||
name: .routeControllerProgressDidChange, | ||
object: nil) | ||
} | ||
|
||
@objc func progressDidChange(_ notification: NSNotification) { | ||
let location = notification.userInfo?[RouteController.NotificationUserInfoKey.locationKey] as? CLLocation | ||
let routeProgress = notification.userInfo?[RouteController.NotificationUserInfoKey.routeProgressKey] as? RouteProgress | ||
let cameraOptions = self.cameraOptions(location, routeProgress: routeProgress) | ||
|
||
delegate?.viewportDataSource(self, didUpdate: cameraOptions) | ||
} | ||
|
||
func cameraOptions(_ location: CLLocation?, routeProgress: RouteProgress? = nil) -> [String: CameraOptions] { | ||
followingMobileCamera.center = location?.coordinate | ||
followingMobileCamera.bearing = location?.course | ||
followingMobileCamera.padding = .zero | ||
followingMobileCamera.zoom = 14.0 | ||
followingMobileCamera.pitch = 0.0 | ||
|
||
overviewMobileCamera.center = location?.coordinate | ||
overviewMobileCamera.bearing = 0.0 | ||
overviewMobileCamera.padding = .zero | ||
overviewMobileCamera.zoom = 10.0 | ||
overviewMobileCamera.pitch = 0.0 | ||
|
||
let cameraOptions = [ | ||
CameraOptions.followingMobileCameraKey: followingMobileCamera, | ||
CameraOptions.overviewMobileCameraKey: overviewMobileCamera | ||
] | ||
|
||
return cameraOptions | ||
} | ||
} | ||
|
||
// MARK: - LocationConsumer delegate | ||
|
||
extension CustomViewportDataSource: LocationConsumer { | ||
|
||
var shouldTrackLocation: Bool { | ||
get { | ||
return true | ||
} | ||
set(newValue) { | ||
// No-op | ||
} | ||
} | ||
|
||
func locationUpdate(newLocation: Location) { | ||
let cameraOptions = self.cameraOptions(newLocation.internalLocation) | ||
delegate?.viewportDataSource(self, didUpdate: cameraOptions) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import UIKit | ||
import MapboxMaps | ||
import MapboxNavigation | ||
|
||
class NavigationCameraDebugView: UIView { | ||
|
||
weak var mapView: MapView? | ||
|
||
var viewportLayer = CALayer() | ||
var anchorLayer = CALayer() | ||
var anchorTextLayer = CATextLayer() | ||
var centerLayer = CALayer() | ||
var centerTextLayer = CATextLayer() | ||
var pitchTextLayer = CATextLayer() | ||
var zoomTextLayer = CATextLayer() | ||
var bearingTextLayer = CATextLayer() | ||
|
||
required init(_ mapView: MapView, frame: CGRect) { | ||
self.mapView = mapView | ||
|
||
super.init(frame: frame) | ||
|
||
isUserInteractionEnabled = false | ||
backgroundColor = .clear | ||
subscribeForNotifications() | ||
|
||
viewportLayer.borderWidth = 3.0 | ||
viewportLayer.borderColor = UIColor.green.cgColor | ||
layer.addSublayer(viewportLayer) | ||
|
||
anchorLayer.backgroundColor = UIColor.red.cgColor | ||
anchorLayer.frame = .init(x: 0.0, y: 0.0, width: 6.0, height: 6.0) | ||
anchorLayer.cornerRadius = 3.0 | ||
layer.addSublayer(anchorLayer) | ||
|
||
anchorTextLayer = CATextLayer() | ||
anchorTextLayer.string = "Anchor" | ||
anchorTextLayer.fontSize = UIFont.systemFontSize | ||
anchorTextLayer.backgroundColor = UIColor.clear.cgColor | ||
anchorTextLayer.foregroundColor = UIColor.red.cgColor | ||
anchorTextLayer.frame = .zero | ||
layer.addSublayer(anchorTextLayer) | ||
|
||
centerLayer.backgroundColor = UIColor.blue.cgColor | ||
centerLayer.frame = .init(x: 0.0, y: 0.0, width: 6.0, height: 6.0) | ||
centerLayer.cornerRadius = 3.0 | ||
layer.addSublayer(centerLayer) | ||
|
||
centerTextLayer = CATextLayer() | ||
centerTextLayer.string = "Center" | ||
centerTextLayer.fontSize = UIFont.systemFontSize | ||
centerTextLayer.backgroundColor = UIColor.clear.cgColor | ||
centerTextLayer.foregroundColor = UIColor.blue.cgColor | ||
centerTextLayer.frame = .zero | ||
layer.addSublayer(centerTextLayer) | ||
|
||
pitchTextLayer = createDefaultTextLayer() | ||
layer.addSublayer(pitchTextLayer) | ||
|
||
zoomTextLayer = createDefaultTextLayer() | ||
layer.addSublayer(zoomTextLayer) | ||
|
||
bearingTextLayer = createDefaultTextLayer() | ||
layer.addSublayer(bearingTextLayer) | ||
} | ||
|
||
func createDefaultTextLayer() -> CATextLayer { | ||
let textLayer = CATextLayer() | ||
textLayer.string = "" | ||
textLayer.fontSize = UIFont.systemFontSize | ||
textLayer.backgroundColor = UIColor.clear.cgColor | ||
textLayer.foregroundColor = UIColor.black.cgColor | ||
textLayer.frame = .zero | ||
|
||
return textLayer | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
deinit { | ||
unsubscribeFromNotifications() | ||
} | ||
|
||
func subscribeForNotifications() { | ||
NotificationCenter.default.addObserver(self, | ||
selector: #selector(navigationCameraViewportDidChange(_:)), | ||
name: .navigationCameraViewportDidChange, | ||
object: nil) | ||
} | ||
|
||
func unsubscribeFromNotifications() { | ||
NotificationCenter.default.removeObserver(self, | ||
name: .navigationCameraViewportDidChange, | ||
object: nil) | ||
} | ||
|
||
@objc func navigationCameraViewportDidChange(_ notification: NSNotification) { | ||
guard let mapView = mapView, | ||
let cameraOptions = notification.userInfo?[NavigationCamera.NotificationUserInfoKey.cameraOptionsKey] as? Dictionary<String, CameraOptions>, | ||
let followingMobileCamera = cameraOptions[CameraOptions.followingMobileCameraKey] else { return } | ||
|
||
if let edgeInsets = followingMobileCamera.padding { | ||
viewportLayer.frame = CGRect(x: edgeInsets.left, | ||
y: edgeInsets.top, | ||
width: mapView.frame.width - edgeInsets.left - edgeInsets.right, | ||
height: mapView.frame.height - edgeInsets.top - edgeInsets.bottom) | ||
} | ||
|
||
if let anchorPosition = followingMobileCamera.anchor { | ||
anchorLayer.position = anchorPosition | ||
anchorTextLayer.frame = .init(x: anchorLayer.frame.origin.x + 5.0, | ||
y: anchorLayer.frame.origin.y + 5.0, | ||
width: 80.0, | ||
height: 20.0) | ||
} | ||
|
||
if let centerCoordinate = followingMobileCamera.center { | ||
centerLayer.position = mapView.point(for: centerCoordinate) | ||
centerTextLayer.frame = .init(x: centerLayer.frame.origin.x + 5.0, | ||
y: centerLayer.frame.origin.y + 5.0, | ||
width: 80.0, | ||
height: 20.0) | ||
} | ||
|
||
if let pitch = followingMobileCamera.pitch { | ||
pitchTextLayer.frame = .init(x: viewportLayer.frame.origin.x + 5.0, | ||
y: viewportLayer.frame.origin.y + 5.0, | ||
width: viewportLayer.frame.size.width - 10.0, | ||
height: 20.0) | ||
pitchTextLayer.string = "Pitch: \(pitch)" | ||
} | ||
|
||
if let zoom = followingMobileCamera.zoom { | ||
zoomTextLayer.frame = .init(x: viewportLayer.frame.origin.x + 5.0, | ||
y: viewportLayer.frame.origin.y + 30.0, | ||
width: viewportLayer.frame.size.width - 10.0, | ||
height: 20.0) | ||
zoomTextLayer.string = "Zoom: \(zoom)" | ||
} | ||
|
||
if let bearing = followingMobileCamera.bearing { | ||
bearingTextLayer.frame = .init(x: viewportLayer.frame.origin.x + 5.0, | ||
y: viewportLayer.frame.origin.y + 55.0, | ||
width: viewportLayer.frame.size.width - 10.0, | ||
height: 20.0) | ||
bearingTextLayer.string = "Bearing: \(bearing)º" | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used for debugging purposes. I intend to keep using it in example application.