diff --git a/src/LegendContent.js b/src/LegendContent.js
new file mode 100644
index 0000000..68be45e
--- /dev/null
+++ b/src/LegendContent.js
@@ -0,0 +1,45 @@
+export const LEGEND_HTML = `
+
+
+
+ Raw Location
+
+
+ FLP Location
+
+
+ FLP = Raw Location
+
+
+
+
+
+
+
+ Actual Pickup
+
+
+
+
+
+
+ Actual Dropoff
+
+
+`;
diff --git a/src/LogTable.js b/src/LogTable.js
index ba326d3..45a7499 100644
--- a/src/LogTable.js
+++ b/src/LogTable.js
@@ -170,7 +170,7 @@ function LogTable(props) {
}, [props.logData.tripLogs, minTime, maxTime, props.filters]);
const columnShortWidth = 50;
const columnRegularWidth = 120;
- const columnLargeWidth = 150;
+ const columnLargeWidth = 152;
const columns = React.useMemo(() => {
const stdColumns = _.filter(
[
diff --git a/src/Map.js b/src/Map.js
index a8148cf..bc49a5e 100644
--- a/src/Map.js
+++ b/src/Map.js
@@ -9,6 +9,7 @@ import { decode } from "s2polyline-ts";
import TrafficPolyline from "./TrafficPolyline";
import { TripObjects } from "./TripObjects";
import { getToggleHandlers } from "./MapToggles.js";
+import { LEGEND_HTML } from "./LegendContent.js";
function MapComponent({
logData,
@@ -109,6 +110,7 @@ function MapComponent({
element: mapDivRef.current,
locationProviders: [locationProviderRef.current],
mapOptions: { mapId, mapTypeControl: true, streetViewControl: true, maxZoom: 22 },
+ automaticViewportMode: "NONE",
});
const map = jsMapView.map;
mapRef.current = map;
@@ -213,6 +215,36 @@ function MapComponent({
bottomControlsWrapper.appendChild(toggleContainer);
map.controls[window.google.maps.ControlPosition.LEFT_BOTTOM].push(bottomControlsWrapper);
+ // Legend Controls
+ const legendToggleContainer = document.createElement("div");
+ legendToggleContainer.className = "map-toggle-container";
+ legendToggleContainer.style.marginTop = "10px";
+ legendToggleContainer.style.marginRight = "10px";
+ legendToggleContainer.style.marginBottom = "0px";
+
+ const legendBtn = document.createElement("button");
+ legendBtn.textContent = "Legend";
+ legendBtn.className = "map-toggle-button";
+ legendToggleContainer.appendChild(legendBtn);
+
+ const legendContentDiv = document.createElement("div");
+ legendContentDiv.style.display = "none";
+ legendContentDiv.innerHTML = LEGEND_HTML;
+
+ legendBtn.onclick = () => {
+ const isHidden = legendContentDiv.style.display === "none";
+ if (isHidden) {
+ legendContentDiv.style.display = "block";
+ legendBtn.classList.add("active");
+ } else {
+ legendContentDiv.style.display = "none";
+ legendBtn.classList.remove("active");
+ }
+ };
+
+ map.controls[window.google.maps.ControlPosition.TOP_RIGHT].push(legendToggleContainer);
+ map.controls[window.google.maps.ControlPosition.TOP_RIGHT].push(legendContentDiv);
+
const centerListener = map.addListener(
"center_changed",
_.debounce(() => {
@@ -441,30 +473,73 @@ function MapComponent({
}
const rawLocation = _.get(locationObj, "rawlocation");
- if (rawLocation?.latitude && rawLocation?.longitude) {
- const rawPos = { lat: rawLocation.latitude, lng: rawLocation.longitude };
- if (vehicleMarkersRef.current.rawLocation) {
- vehicleMarkersRef.current.rawLocation.setPosition(rawPos);
- if (!vehicleMarkersRef.current.rawLocation.getMap()) {
- vehicleMarkersRef.current.rawLocation.setMap(map);
+ const flpLocation = _.get(locationObj, "flplocation");
+
+ const rawLat = rawLocation?.latitude;
+ const rawLng = rawLocation?.longitude;
+ const flpLat = flpLocation?.latitude;
+ const flpLng = flpLocation?.longitude;
+
+ const hasRaw = rawLat !== undefined && rawLng !== undefined;
+ const hasFlp = flpLat !== undefined && flpLng !== undefined;
+ const isMatch = hasRaw && hasFlp && rawLat === flpLat && rawLng === flpLng;
+
+ const updateMarker = (markerRefName, position, color, zIndex, scale = 2) => {
+ if (!position) {
+ if (vehicleMarkersRef.current[markerRefName]) {
+ vehicleMarkersRef.current[markerRefName].setMap(null);
+ }
+ return;
+ }
+
+ const pos = { lat: position.latitude, lng: position.longitude };
+ if (vehicleMarkersRef.current[markerRefName]) {
+ vehicleMarkersRef.current[markerRefName].setPosition(pos);
+ if (!vehicleMarkersRef.current[markerRefName].getMap()) {
+ vehicleMarkersRef.current[markerRefName].setMap(map);
+ }
+ const icon = vehicleMarkersRef.current[markerRefName].getIcon();
+ if (icon.fillColor !== color || icon.scale !== scale) {
+ icon.fillColor = color;
+ icon.strokeColor = color;
+ icon.scale = scale;
+ vehicleMarkersRef.current[markerRefName].setIcon(icon);
}
} else {
- vehicleMarkersRef.current.rawLocation = new window.google.maps.Marker({
- position: rawPos,
+ vehicleMarkersRef.current[markerRefName] = new window.google.maps.Marker({
+ position: pos,
map,
icon: {
path: window.google.maps.SymbolPath.CIRCLE,
- fillColor: "#FF0000",
+ fillColor: color,
fillOpacity: 1,
- scale: 2,
- strokeColor: "#FF0000",
+ scale: scale,
+ strokeColor: color,
strokeWeight: 1,
},
- zIndex: 8,
+ zIndex: zIndex,
});
}
- } else if (vehicleMarkersRef.current.rawLocation) {
- vehicleMarkersRef.current.rawLocation.setMap(null);
+ };
+
+ if (isMatch) {
+ updateMarker("matchLocation", rawLocation, "#C71585", 8, 3);
+ updateMarker("rawLocation", null);
+ updateMarker("flpLocation", null);
+ } else {
+ updateMarker("matchLocation", null);
+
+ if (hasRaw) {
+ updateMarker("rawLocation", rawLocation, "#FF0000", 8, 2);
+ } else {
+ updateMarker("rawLocation", null);
+ }
+
+ if (hasFlp) {
+ updateMarker("flpLocation", flpLocation, "#4285F4", 8, 2);
+ } else {
+ updateMarker("flpLocation", null);
+ }
}
if (isFollowingVehicle) {