Skip to content

Commit f3268f5

Browse files
authored
Align DVA example with Android (#2446)
1 parent a58e3c1 commit f3268f5

File tree

3 files changed

+7246
-2921
lines changed

3 files changed

+7246
-2921
lines changed

Sources/Examples/All Examples/Annotations/DynamicViewAnnotationExample.swift

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private let simulatedCoordinate = CLLocationCoordinate2D(latitude: 37.6421, long
88
final class DynamicViewAnnotationExample: UIViewController, ExampleProtocol {
99
private var mapView: MapView!
1010
private var cancelables = Set<AnyCancelable>()
11+
private var puckRenderCancellable: AnyCancelable?
1112

1213
private var routes = [Route]() {
1314
didSet {
@@ -21,8 +22,8 @@ final class DynamicViewAnnotationExample: UIViewController, ExampleProtocol {
2122
self?.select(route: route)
2223
}
2324
}
24-
if let last = routes.last {
25-
select(route: last, animated: false)
25+
if let first = routes.first {
26+
select(route: first, animated: false)
2627
}
2728
}
2829
}
@@ -56,13 +57,6 @@ final class DynamicViewAnnotationExample: UIViewController, ExampleProtocol {
5657

5758
updateModeButton()
5859

59-
mapView.location.override(
60-
locationProvider: Signal(just: [
61-
Location(
62-
coordinate: simulatedCoordinate,
63-
bearing: 168.8)
64-
]),
65-
headingProvider: Signal(just: Heading(direction: 180, accuracy: 0)))
6660
mapView.location.options = LocationOptions(puckType: .puck2D(.init(topImage: UIImage(named: "dash-puck"))), puckBearing: .heading, puckBearingEnabled: true)
6761

6862
mapView.viewport.options.usesSafeAreaInsetsAsPadding = true
@@ -101,6 +95,49 @@ final class DynamicViewAnnotationExample: UIViewController, ExampleProtocol {
10195
}
10296
}
10397

98+
private func setupLocationSimulation(route: Route) {
99+
guard case Turf.Geometry.lineString(let line) = route.feature.geometry! else {
100+
return
101+
}
102+
103+
var coordinates = line.coordinates
104+
var lastLocation: CLLocationCoordinate2D = coordinates.first!
105+
106+
var locationHandler: (([Location]) -> Void)?
107+
var headingHandler: ((Heading) -> Void)?
108+
var timer: Timer?
109+
let locationSignal: Signal<[Location]> = Signal { handler in
110+
locationHandler = handler
111+
return AnyCancelable {
112+
timer?.invalidate()
113+
}
114+
}
115+
let headingSignal: Signal<Heading> = Signal { handler in
116+
headingHandler = handler
117+
return AnyCancelable {}
118+
}
119+
120+
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
121+
guard !coordinates.isEmpty else {
122+
timer.invalidate()
123+
return
124+
}
125+
let currentLocation = coordinates.removeFirst()
126+
let currentDirection = lastLocation.direction(to: currentLocation)
127+
128+
locationHandler?([Location(coordinate: lastLocation)])
129+
headingHandler?(Heading(direction: currentDirection, accuracy: 0))
130+
131+
lastLocation = currentLocation
132+
}
133+
134+
mapView.location.override(locationProvider: locationSignal, headingProvider: headingSignal)
135+
136+
puckRenderCancellable = mapView.location.onPuckRender.observe { data in
137+
route.updateProgress(with: data.location.coordinate)
138+
}
139+
}
140+
104141
private func select(route: Route, animated: Bool = true) {
105142
// Move selected route layer on top of unselected route layers
106143
let routeLayersIds = Set(routes.map(\.layerId))
@@ -118,35 +155,36 @@ final class DynamicViewAnnotationExample: UIViewController, ExampleProtocol {
118155
if !driveMode {
119156
updateViewport(animated: animated)
120157
}
158+
setupLocationSimulation(route: route)
121159
}
122160

123161
@objc private func changeMode() {
124162
self.driveMode.toggle()
125163
updateModeButton()
126164

127-
hideAnnotations(true)
128165
updateViewport(animated: true) { [weak self] in
129-
self?.hideAnnotations(false)
130-
}
131-
routes.forEach {
132-
$0.updateProgress(with: driveMode ? simulatedCoordinate : nil)
166+
guard let self else { return }
167+
168+
self.hideInactiveRoutes(self.driveMode)
133169
}
134170
}
135171

136172
private func updateModeButton() {
137-
modeButton.setTitle("Mode: \(driveMode ? "Drive" : "Overview")", for: .normal)
173+
modeButton.setTitle("Mode: \(driveMode ? "Overview" : "Drive")", for: .normal)
138174
}
139175

140-
private func hideAnnotations(_ hidden: Bool) {
176+
private func hideInactiveRoutes(_ hidden: Bool) {
141177
routes.forEach {
142-
$0.etaAnnotation?.visible = !hidden
178+
$0.visible = $0.selected || hidden
143179
}
144180
}
145181

146182
private func updateViewport(animated: Bool, completion: (() -> Void)? = nil) {
147183
var viewportState: ViewportState?
148184
if driveMode {
149-
viewportState = mapView.viewport.makeFollowPuckViewportState(options: .init(zoom: 17, bearing: .course, pitch: 49))
185+
viewportState = mapView.viewport.makeFollowPuckViewportState(options:
186+
.init(padding: .init(top: 100, left: 100, bottom: 100, right: 100), zoom: 18, bearing: .heading, pitch: 70)
187+
)
150188
} else {
151189
if let route = routes.first(where: \.selected), let geometry = route.feature.geometry {
152190
let coordPadding = UIEdgeInsets(allEdges: 20)
@@ -199,6 +237,9 @@ private final class Route {
199237
var selected: Bool = false {
200238
didSet { updateSelected() }
201239
}
240+
var visible = true {
241+
didSet { updateVisible() }
242+
}
202243
var layerId: String { "route-\(name)" }
203244
private(set) var etaAnnotation: ViewAnnotation?
204245
private var etaView: ETAView?
@@ -220,7 +261,7 @@ private final class Route {
220261
case let .lineString(s) = feature.geometry,
221262
let doneDistance = s.distance(to: coordinate),
222263
let length = s.distance() {
223-
progress = doneDistance / length + 0.0005
264+
progress = doneDistance / length
224265
}
225266

226267
try? mapView?.mapboxMap.setLayerProperty(for: layerId, property: "line-trim-offset", value: [0, progress])
@@ -304,6 +345,10 @@ private final class Route {
304345
etaAnnotation?.setNeedsUpdateSize()
305346
}
306347

348+
private func updateVisible() {
349+
try? mapView?.mapboxMap.setLayerProperty(for: layerId, property: "visibility", value: visible ? "visible" : "none")
350+
}
351+
307352
static func load(name: String, time: String) -> Route {
308353
let data = NSDataAsset(name: name)!.data
309354
let feature = try! JSONDecoder().decode(Feature.self, from: data)

0 commit comments

Comments
 (0)