@@ -297,6 +297,10 @@ open class NavigationMapView: UIView {
297297 parentLayerIdentifier = addRouteCasingLayer ( route,
298298 below: parentLayerIdentifier,
299299 isMainRoute: index == 0 )
300+
301+ if index == 0 && routeLineTracksTraversal {
302+ parentLayerIdentifier = addTraversedRouteLayer ( route, below: parentLayerIdentifier)
303+ }
300304 }
301305
302306 continuousAlternatives? . forEach { routeAlternative in
@@ -336,6 +340,7 @@ open class NavigationMapView: UIView {
336340 sourceIdentifiers. insert ( $0. element. identifier ( . restrictedRouteAreaSource) )
337341 layerIdentifiers. insert ( $0. element. identifier ( . route( isMainRoute: $0. offset == 0 ) ) )
338342 layerIdentifiers. insert ( $0. element. identifier ( . routeCasing( isMainRoute: $0. offset == 0 ) ) )
343+ layerIdentifiers. insert ( $0. element. identifier ( . traversedRoute) )
339344 layerIdentifiers. insert ( $0. element. identifier ( . restrictedRouteAreaRoute) )
340345 }
341346
@@ -362,14 +367,6 @@ open class NavigationMapView: UIView {
362367 mapView. mapboxMap. style. removeSources ( sourceIdentifiers)
363368 }
364369
365- func removeRestrictedRouteArea( ) {
366- guard let sourceIdentifier = routes? . first? . identifier ( . restrictedRouteAreaSource) ,
367- let layerIdentifier = routes? . first? . identifier ( . restrictedRouteAreaRoute) else { return }
368-
369- mapView. mapboxMap. style. removeLayers ( Set ( [ layerIdentifier] ) )
370- mapView. mapboxMap. style. removeSources ( Set ( [ sourceIdentifier] ) )
371- }
372-
373370 /**
374371 Shows the step arrow given the current `RouteProgress`.
375372
@@ -625,7 +622,7 @@ open class NavigationMapView: UIView {
625622 let shape = delegate? . navigationMapView ( self , shapeFor: route) ?? defaultShape
626623
627624 let geoJSONSource = self . geoJSONSource ( shape)
628- let sourceIdentifier = route. identifier ( . source( isMainRoute: isMainRoute, isSourceCasing: true ) )
625+ let sourceIdentifier = route. identifier ( . source( isMainRoute: isMainRoute, isSourceCasing: false ) )
629626
630627 do {
631628 if mapView. mapboxMap. style. sourceExists ( withId: sourceIdentifier) {
@@ -719,7 +716,7 @@ open class NavigationMapView: UIView {
719716 let shape = delegate? . navigationMapView ( self , casingShapeFor: route) ?? defaultShape
720717
721718 let geoJSONSource = self . geoJSONSource ( shape)
722- let sourceIdentifier = route. identifier ( . source( isMainRoute: isMainRoute, isSourceCasing: isMainRoute ) )
719+ let sourceIdentifier = route. identifier ( . source( isMainRoute: isMainRoute, isSourceCasing: true ) )
723720
724721 do {
725722 if mapView. mapboxMap. style. sourceExists ( withId: sourceIdentifier) {
@@ -787,6 +784,65 @@ open class NavigationMapView: UIView {
787784 return layerIdentifier
788785 }
789786
787+ @discardableResult func addTraversedRouteLayer( _ route: Route , below parentLayerIndentifier: String ? = nil ) -> String ? {
788+ guard let defaultShape = route. shape else { return nil }
789+
790+ // The traversed route layer should have the source as the main route casing source.
791+ let sourceIdentifier = route. identifier ( . source( isMainRoute: true , isSourceCasing: true ) )
792+
793+ if !mapView. mapboxMap. style. sourceExists ( withId: sourceIdentifier) {
794+ let shape = delegate? . navigationMapView ( self , casingShapeFor: route) ?? defaultShape
795+ let geoJSONSource = self . geoJSONSource ( shape)
796+ do {
797+ try mapView. mapboxMap. style. addSource ( geoJSONSource, id: sourceIdentifier)
798+ } catch {
799+ Log . error ( " Failed to add route casing source \( sourceIdentifier) for traversed route with error: \( error. localizedDescription) . " ,
800+ category: . navigationUI)
801+ }
802+ }
803+
804+ var lineLayer : LineLayer ? = nil
805+ let layerIdentifier = route. identifier ( . traversedRoute)
806+
807+ let layerAlreadyExists = mapView. mapboxMap. style. layerExists ( withId: layerIdentifier)
808+ if layerAlreadyExists {
809+ lineLayer = try ? mapView. mapboxMap. style. layer ( withId: layerIdentifier) as? LineLayer
810+ }
811+
812+ if lineLayer == nil {
813+ lineLayer = LineLayer ( id: layerIdentifier)
814+ lineLayer? . source = sourceIdentifier
815+ lineLayer? . lineColor = . constant( . init( traversedRouteColor) )
816+ // The traversed route layer should have the same width as the main route casing layer.
817+ lineLayer? . lineWidth = . expression( Expression . routeLineWidthExpression ( 1.5 ) )
818+ lineLayer? . lineJoin = . constant( . round)
819+ lineLayer? . lineCap = . constant( . round)
820+ }
821+
822+ if let lineLayer = lineLayer {
823+ do {
824+ var layerPosition : MapboxMaps . LayerPosition ? = nil
825+ if let parentLayerIndentifier = parentLayerIndentifier, mapView. mapboxMap. style. layerExists ( withId: parentLayerIndentifier) {
826+ layerPosition = . below( parentLayerIndentifier)
827+ } else {
828+ layerPosition = self . layerPosition ( for: layerIdentifier, route: route)
829+ }
830+ if layerAlreadyExists {
831+ if let layerPosition = layerPosition {
832+ try mapView. mapboxMap. style. moveLayer ( withId: layerIdentifier, to: layerPosition)
833+ }
834+ } else {
835+ try mapView. mapboxMap. style. addPersistentLayer ( lineLayer, layerPosition: layerPosition)
836+ }
837+ } catch {
838+ Log . error ( " Failed to add traversed route layer \( layerIdentifier) with error: \( error. localizedDescription) . " ,
839+ category: . navigationUI)
840+ }
841+ }
842+
843+ return layerIdentifier
844+ }
845+
790846 func geoJSONSource( _ shape: LineString ) -> GeoJSONSource {
791847 var geoJSONSource = GeoJSONSource ( )
792848 geoJSONSource. data = . geometry( . lineString( shape) )
@@ -1750,6 +1806,7 @@ open class NavigationMapView: UIView {
17501806 LayerIdentifier . buildingExtrusionLayer,
17511807 route? . identifier ( . routeCasing( isMainRoute: false ) ) ,
17521808 route? . identifier ( . route( isMainRoute: false ) ) ,
1809+ route? . identifier ( . traversedRoute) ,
17531810 route? . identifier ( . routeCasing( isMainRoute: true ) ) ,
17541811 route? . identifier ( . route( isMainRoute: true ) ) ,
17551812 route? . identifier ( . restrictedRouteAreaRoute)
0 commit comments