@@ -9,6 +9,7 @@ import { decode } from "s2polyline-ts";
99import TrafficPolyline from "./TrafficPolyline" ;
1010import { TripObjects } from "./TripObjects" ;
1111import { getToggleHandlers } from "./MapToggles.js" ;
12+ import { LEGEND_HTML } from "./LegendContent.js" ;
1213
1314function MapComponent ( {
1415 logData,
@@ -109,6 +110,7 @@ function MapComponent({
109110 element : mapDivRef . current ,
110111 locationProviders : [ locationProviderRef . current ] ,
111112 mapOptions : { mapId, mapTypeControl : true , streetViewControl : true , maxZoom : 22 } ,
113+ automaticViewportMode : "NONE" ,
112114 } ) ;
113115 const map = jsMapView . map ;
114116 mapRef . current = map ;
@@ -213,6 +215,36 @@ function MapComponent({
213215 bottomControlsWrapper . appendChild ( toggleContainer ) ;
214216 map . controls [ window . google . maps . ControlPosition . LEFT_BOTTOM ] . push ( bottomControlsWrapper ) ;
215217
218+ // Legend Controls
219+ const legendToggleContainer = document . createElement ( "div" ) ;
220+ legendToggleContainer . className = "map-toggle-container" ;
221+ legendToggleContainer . style . marginTop = "10px" ;
222+ legendToggleContainer . style . marginRight = "10px" ;
223+ legendToggleContainer . style . marginBottom = "0px" ;
224+
225+ const legendBtn = document . createElement ( "button" ) ;
226+ legendBtn . textContent = "Legend" ;
227+ legendBtn . className = "map-toggle-button" ;
228+ legendToggleContainer . appendChild ( legendBtn ) ;
229+
230+ const legendContentDiv = document . createElement ( "div" ) ;
231+ legendContentDiv . style . display = "none" ;
232+ legendContentDiv . innerHTML = LEGEND_HTML ;
233+
234+ legendBtn . onclick = ( ) => {
235+ const isHidden = legendContentDiv . style . display === "none" ;
236+ if ( isHidden ) {
237+ legendContentDiv . style . display = "block" ;
238+ legendBtn . classList . add ( "active" ) ;
239+ } else {
240+ legendContentDiv . style . display = "none" ;
241+ legendBtn . classList . remove ( "active" ) ;
242+ }
243+ } ;
244+
245+ map . controls [ window . google . maps . ControlPosition . TOP_RIGHT ] . push ( legendToggleContainer ) ;
246+ map . controls [ window . google . maps . ControlPosition . TOP_RIGHT ] . push ( legendContentDiv ) ;
247+
216248 const centerListener = map . addListener (
217249 "center_changed" ,
218250 _ . debounce ( ( ) => {
@@ -441,30 +473,73 @@ function MapComponent({
441473 }
442474
443475 const rawLocation = _ . get ( locationObj , "rawlocation" ) ;
444- if ( rawLocation ?. latitude && rawLocation ?. longitude ) {
445- const rawPos = { lat : rawLocation . latitude , lng : rawLocation . longitude } ;
446- if ( vehicleMarkersRef . current . rawLocation ) {
447- vehicleMarkersRef . current . rawLocation . setPosition ( rawPos ) ;
448- if ( ! vehicleMarkersRef . current . rawLocation . getMap ( ) ) {
449- vehicleMarkersRef . current . rawLocation . setMap ( map ) ;
476+ const flpLocation = _ . get ( locationObj , "flplocation" ) ;
477+
478+ const rawLat = rawLocation ?. latitude ;
479+ const rawLng = rawLocation ?. longitude ;
480+ const flpLat = flpLocation ?. latitude ;
481+ const flpLng = flpLocation ?. longitude ;
482+
483+ const hasRaw = rawLat !== undefined && rawLng !== undefined ;
484+ const hasFlp = flpLat !== undefined && flpLng !== undefined ;
485+ const isMatch = hasRaw && hasFlp && rawLat === flpLat && rawLng === flpLng ;
486+
487+ const updateMarker = ( markerRefName , position , color , zIndex , scale = 2 ) => {
488+ if ( ! position ) {
489+ if ( vehicleMarkersRef . current [ markerRefName ] ) {
490+ vehicleMarkersRef . current [ markerRefName ] . setMap ( null ) ;
491+ }
492+ return ;
493+ }
494+
495+ const pos = { lat : position . latitude , lng : position . longitude } ;
496+ if ( vehicleMarkersRef . current [ markerRefName ] ) {
497+ vehicleMarkersRef . current [ markerRefName ] . setPosition ( pos ) ;
498+ if ( ! vehicleMarkersRef . current [ markerRefName ] . getMap ( ) ) {
499+ vehicleMarkersRef . current [ markerRefName ] . setMap ( map ) ;
500+ }
501+ const icon = vehicleMarkersRef . current [ markerRefName ] . getIcon ( ) ;
502+ if ( icon . fillColor !== color || icon . scale !== scale ) {
503+ icon . fillColor = color ;
504+ icon . strokeColor = color ;
505+ icon . scale = scale ;
506+ vehicleMarkersRef . current [ markerRefName ] . setIcon ( icon ) ;
450507 }
451508 } else {
452- vehicleMarkersRef . current . rawLocation = new window . google . maps . Marker ( {
453- position : rawPos ,
509+ vehicleMarkersRef . current [ markerRefName ] = new window . google . maps . Marker ( {
510+ position : pos ,
454511 map,
455512 icon : {
456513 path : window . google . maps . SymbolPath . CIRCLE ,
457- fillColor : "#FF0000" ,
514+ fillColor : color ,
458515 fillOpacity : 1 ,
459- scale : 2 ,
460- strokeColor : "#FF0000" ,
516+ scale : scale ,
517+ strokeColor : color ,
461518 strokeWeight : 1 ,
462519 } ,
463- zIndex : 8 ,
520+ zIndex : zIndex ,
464521 } ) ;
465522 }
466- } else if ( vehicleMarkersRef . current . rawLocation ) {
467- vehicleMarkersRef . current . rawLocation . setMap ( null ) ;
523+ } ;
524+
525+ if ( isMatch ) {
526+ updateMarker ( "matchLocation" , rawLocation , "#C71585" , 8 , 3 ) ;
527+ updateMarker ( "rawLocation" , null ) ;
528+ updateMarker ( "flpLocation" , null ) ;
529+ } else {
530+ updateMarker ( "matchLocation" , null ) ;
531+
532+ if ( hasRaw ) {
533+ updateMarker ( "rawLocation" , rawLocation , "#FF0000" , 8 , 2 ) ;
534+ } else {
535+ updateMarker ( "rawLocation" , null ) ;
536+ }
537+
538+ if ( hasFlp ) {
539+ updateMarker ( "flpLocation" , flpLocation , "#4285F4" , 8 , 2 ) ;
540+ } else {
541+ updateMarker ( "flpLocation" , null ) ;
542+ }
468543 }
469544
470545 if ( isFollowingVehicle ) {
0 commit comments