99import {
1010 getStatusColor ,
1111 createStopMarkerElement ,
12- createArrowElement ,
1312 createVehicleArrowElement ,
1413} from '../utils/mapStyles'
1514
@@ -20,11 +19,24 @@ export const useMapLayers = (
2019 const vehicleMarkers = useRef < mapboxgl . Marker [ ] > ( [ ] )
2120 const tripSources = useRef < string [ ] > ( [ ] )
2221 const activePopups = useRef < mapboxgl . Popup [ ] > ( [ ] )
22+ const selectedTripId = useRef < number | null > ( null )
2323
2424 const closeAllPopups = useCallback ( ( ) => {
2525 activePopups . current . forEach ( ( popup ) => popup . remove ( ) )
2626 activePopups . current = [ ]
27- } , [ ] )
27+
28+ // Reset selected trip and update all trip patterns
29+ if ( selectedTripId . current ) {
30+ const prevSelectedId = selectedTripId . current
31+ selectedTripId . current = null
32+
33+ // Update the previously selected trip pattern back to normal
34+ const layerId = `trip-${ prevSelectedId } -layer`
35+ if ( map . current ?. getLayer ( layerId ) ) {
36+ map . current . setPaintProperty ( layerId , 'line-pattern' , 'trip-chevron' )
37+ }
38+ }
39+ } , [ map ] )
2840
2941 // Add click-outside behavior to close all popups
3042 const setupMapClickHandler = useCallback ( ( ) => {
@@ -192,45 +204,51 @@ export const useMapLayers = (
192204 } )
193205
194206 const statusColor = getStatusColor ( trip . status )
207+ const patternId = 'trip-chevron'
208+
209+ // Load chevron pattern images if they don't exist
210+ if ( ! map . current ! . hasImage ( 'trip-chevron' ) ) {
211+ map . current ! . loadImage (
212+ '/src/assets/trip-chevron.png' ,
213+ ( error , image ) => {
214+ if ( error ) throw error
215+ if ( image && ! map . current ! . hasImage ( 'trip-chevron' ) ) {
216+ map . current ! . addImage ( 'trip-chevron' , image , { sdf : false } )
217+ }
218+ }
219+ )
220+ }
221+
222+ if ( ! map . current ! . hasImage ( 'trip-chevron-selected' ) ) {
223+ map . current ! . loadImage (
224+ '/src/assets/trip-chevron-selected.png' ,
225+ ( error , image ) => {
226+ if ( error ) throw error
227+ if ( image && ! map . current ! . hasImage ( 'trip-chevron-selected' ) ) {
228+ map . current ! . addImage ( 'trip-chevron-selected' , image , {
229+ sdf : false ,
230+ } )
231+ }
232+ }
233+ )
234+ }
195235
196236 map . current ! . addLayer ( {
197237 id : `${ sourceId } -layer` ,
198238 type : 'line' ,
199239 source : sourceId ,
200240 layout : {
201- 'line-join' : 'round ' ,
241+ 'line-join' : 'none ' ,
202242 'line-cap' : 'round' ,
203243 } ,
204244 paint : {
205245 'line-color' : statusColor ,
206- 'line-width' : 5 ,
246+ 'line-pattern' : patternId ,
247+ 'line-width' : 16 ,
248+ 'line-opacity' : 1.0 ,
207249 } ,
208250 } )
209251
210- // Add directional arrows at midpoints
211- for ( let i = 0 ; i < coordinates . length - 1 ; i ++ ) {
212- const start = coordinates [ i ]
213- const end = coordinates [ i + 1 ]
214- const midPoint = [ ( start [ 0 ] + end [ 0 ] ) / 2 , ( start [ 1 ] + end [ 1 ] ) / 2 ]
215-
216- // Calculate bearing for arrow direction
217- const bearing =
218- ( Math . atan2 ( end [ 1 ] - start [ 1 ] , end [ 0 ] - start [ 0 ] ) * 180 ) / Math . PI
219-
220- // Create arrow marker
221- const arrowElement = createArrowElement ( statusColor )
222- arrowElement . style . transform = `rotate(${ bearing + 90 } deg)`
223- arrowElement . style . opacity = showTrips ? '0.8' : '0'
224- arrowElement . classList . add ( 'trip-arrow' ) // Add class for easier identification
225-
226- new mapboxgl . Marker ( {
227- element : arrowElement ,
228- anchor : 'center' ,
229- } )
230- . setLngLat ( midPoint as [ number , number ] )
231- . addTo ( map . current ! )
232- }
233-
234252 // Add click handler for trip lines
235253 map . current ! . on ( 'click' , `${ sourceId } -layer` , ( e ) => {
236254 const coordinates = e . lngLat
@@ -249,11 +267,34 @@ export const useMapLayers = (
249267 closeAllPopups ( )
250268 activePopups . current . push ( popup )
251269
252- // Remove from active popups when closed
270+ // Update selected trip pattern
271+ selectedTripId . current = trip . id
272+ const layerId = `${ sourceId } -layer`
273+ if ( map . current ?. getLayer ( layerId ) ) {
274+ map . current . setPaintProperty (
275+ layerId ,
276+ 'line-pattern' ,
277+ 'trip-chevron-selected'
278+ )
279+ }
280+
281+ // Remove from active popups when closed and reset pattern
253282 popup . on ( 'close' , ( ) => {
254283 activePopups . current = activePopups . current . filter (
255284 ( p ) => p !== popup
256285 )
286+
287+ // Reset pattern back to normal when popup closes
288+ if ( selectedTripId . current === trip . id ) {
289+ selectedTripId . current = null
290+ if ( map . current ?. getLayer ( layerId ) ) {
291+ map . current . setPaintProperty (
292+ layerId ,
293+ 'line-pattern' ,
294+ 'trip-chevron'
295+ )
296+ }
297+ }
257298 } )
258299
259300 popup . setLngLat ( coordinates ) . addTo ( map . current ! )
0 commit comments