diff --git a/app/javascript/maps/polylines.js b/app/javascript/maps/polylines.js index ba7e15cf..50abecc9 100644 --- a/app/javascript/maps/polylines.js +++ b/app/javascript/maps/polylines.js @@ -170,51 +170,54 @@ export function addHighlightOnHover(polylineGroup, map, polylineCoordinates, use let hoverPopup = null; - polylineGroup.on("mouseover", function (e) { - let closestSegment = null; - let minDistance = Infinity; - let currentSpeed = 0; + // Add events to both group and individual polylines + polylineGroup.eachLayer((layer) => { + if (layer instanceof L.Polyline) { + layer.on("mouseover", function (e) { + console.log("Individual polyline mouseover", e); + handleMouseOver(e); + }); - polylineGroup.eachLayer((layer) => { - if (layer instanceof L.Polyline) { - const layerLatLngs = layer.getLatLngs(); - const distance = pointToLineDistance(e.latlng, layerLatLngs[0], layerLatLngs[1]); + layer.on("mouseout", function (e) { + console.log("Individual polyline mouseout", e); + handleMouseOut(e); + }); + } + }); - if (distance < minDistance) { - minDistance = distance; - closestSegment = layer; + function handleMouseOver(e) { + console.log('Individual polyline mouseover', e); - const startIdx = polylineCoordinates.findIndex(p => { - const latMatch = Math.abs(p[0] - layerLatLngs[0].lat) < 0.0000001; - const lngMatch = Math.abs(p[1] - layerLatLngs[0].lng) < 0.0000001; - return latMatch && lngMatch; - }); + // Handle both direct layer events and group propagated events + const layer = e.layer || e.target; + let speed = 0; - if (startIdx !== -1 && startIdx < polylineCoordinates.length - 1) { - currentSpeed = calculateSpeed( - polylineCoordinates[startIdx], - polylineCoordinates[startIdx + 1] - ); - } + if (layer instanceof L.Polyline) { + // Get the coordinates array from the layer + const coords = layer.getLatLngs(); + if (coords && coords.length >= 2) { + const startPoint = coords[0]; + const endPoint = coords[coords.length - 1]; + + // Find the corresponding markers for these coordinates + const startMarkerData = polylineCoordinates.find(m => + m[0] === startPoint.lat && m[1] === startPoint.lng + ); + const endMarkerData = polylineCoordinates.find(m => + m[0] === endPoint.lat && m[1] === endPoint.lng + ); + + // Calculate speed if we have both markers + if (startMarkerData && endMarkerData) { + speed = startMarkerData[5] || endMarkerData[5] || 0; } } - }); + } - // Apply highlight style to all segments - polylineGroup.eachLayer((layer) => { - if (layer instanceof L.Polyline) { - const highlightStyle = { - weight: 5, - opacity: 1 - }; - - // Only change color to yellow if speed colors are disabled - if (!userSettings.speed_colored_routes) { - highlightStyle.color = '#ffff00'; - } - - layer.setStyle(highlightStyle); - } + layer.setStyle({ + weight: 8, + opacity: 0.8, + color: '#FFD700' }); startMarker.addTo(map); @@ -225,7 +228,7 @@ export function addHighlightOnHover(polylineGroup, map, polylineCoordinates, use End: ${lastTimestamp}
Duration: ${timeOnRoute}
Total Distance: ${formatDistance(totalDistance, distanceUnit)}
- Current Speed: ${Math.round(currentSpeed)} km/h + Current Speed: ${Math.round(speed)} km/h `; if (hoverPopup) { @@ -236,16 +239,15 @@ export function addHighlightOnHover(polylineGroup, map, polylineCoordinates, use .setLatLng(e.latlng) .setContent(popupContent) .openOn(map); - }); + } - polylineGroup.on("mouseout", function () { - // Restore original style + function handleMouseOut(e) { polylineGroup.eachLayer((layer) => { if (layer instanceof L.Polyline) { const originalStyle = { weight: 3, opacity: userSettings.route_opacity, - color: layer.options.originalColor // Use the stored original color + color: layer.options.originalColor }; layer.setStyle(originalStyle); @@ -257,16 +259,31 @@ export function addHighlightOnHover(polylineGroup, map, polylineCoordinates, use } map.removeLayer(startMarker); map.removeLayer(endMarker); - }); + } + // Keep the original group events as a fallback + polylineGroup.on("mouseover", handleMouseOver); + polylineGroup.on("mouseout", handleMouseOut); + + // Keep the click event polylineGroup.on("click", function () { map.fitBounds(polylineGroup.getBounds()); }); } export function createPolylinesLayer(markers, map, timezone, routeOpacity, userSettings, distanceUnit) { - // Create a canvas renderer - const renderer = L.canvas({ padding: 0.5 }); + // Create a custom pane for our polylines with higher z-index + if (!map.getPane('polylinesPane')) { + map.createPane('polylinesPane'); + map.getPane('polylinesPane').style.zIndex = 450; // Above the default overlay pane (400) + } + + const renderer = L.canvas({ + padding: 0.5, + pane: 'polylinesPane' + }); + + console.log("Creating polylines layer with markers:", markers.length); const splitPolylines = []; let currentPolyline = []; @@ -295,9 +312,15 @@ export function createPolylinesLayer(markers, map, timezone, routeOpacity, userS splitPolylines.push(currentPolyline); } - return L.layerGroup( - splitPolylines.map((polylineCoordinates) => { + console.log("Split into polyline groups:", splitPolylines.length); + + // Create the layer group with the polylines + const layerGroup = L.layerGroup( + splitPolylines.map((polylineCoordinates, groupIndex) => { + console.log(`Creating group ${groupIndex} with coordinates:`, polylineCoordinates.length); + const segmentGroup = L.featureGroup(); + const segments = []; for (let i = 0; i < polylineCoordinates.length - 1; i++) { const speed = calculateSpeed(polylineCoordinates[i], polylineCoordinates[i + 1]); @@ -309,25 +332,77 @@ export function createPolylinesLayer(markers, map, timezone, routeOpacity, userS [polylineCoordinates[i + 1][0], polylineCoordinates[i + 1][1]] ], { - renderer: renderer, // Use canvas renderer + renderer: renderer, color: color, originalColor: color, opacity: routeOpacity, weight: 3, speed: speed, - startTime: polylineCoordinates[i][4], - endTime: polylineCoordinates[i + 1][4] + interactive: true, + pane: 'polylinesPane', + bubblingMouseEvents: false } ); + segments.push(segment); segmentGroup.addLayer(segment); } + // Add mouseover/mouseout to the entire group + segmentGroup.on('mouseover', function(e) { + console.log("Group mouseover", groupIndex); + L.DomEvent.stopPropagation(e); + segments.forEach(segment => { + segment.setStyle({ + weight: 8, + opacity: 1 + }); + if (map.hasLayer(segment)) { + segment.bringToFront(); + } + }); + }); + + segmentGroup.on('mouseout', function(e) { + console.log("Group mouseout", groupIndex); + L.DomEvent.stopPropagation(e); + segments.forEach(segment => { + segment.setStyle({ + weight: 3, + opacity: routeOpacity, + color: segment.options.originalColor + }); + }); + }); + + // Make the group interactive + segmentGroup.options.interactive = true; + segmentGroup.options.bubblingMouseEvents = false; + + // Add the hover functionality to the group addHighlightOnHover(segmentGroup, map, polylineCoordinates, userSettings, distanceUnit); return segmentGroup; }) - ).addTo(map); + ); + + // Add CSS to ensure our pane receives mouse events + const style = document.createElement('style'); + style.textContent = ` + .leaflet-polylinesPane-pane { + pointer-events: auto !important; + } + .leaflet-polylinesPane-pane canvas { + pointer-events: auto !important; + } + `; + document.head.appendChild(style); + + // Add to map and return + layerGroup.addTo(map); + console.log("Layer group added to map"); + + return layerGroup; } export function updatePolylinesColors(polylinesLayer, useSpeedColors) { diff --git a/app/javascript/maps/popups.js b/app/javascript/maps/popups.js index dee74dc5..cba49a22 100644 --- a/app/javascript/maps/popups.js +++ b/app/javascript/maps/popups.js @@ -8,6 +8,9 @@ export function createPopupContent(marker, timezone, distanceUnit) { marker[3] = marker[3] * 3.28084; } + // convert marker[5] from m/s to km/h and round to nearest integer + marker[5] = Math.round(marker[5] * 3.6); + return ` Timestamp: ${formatDate(marker[4], timezone)}
Latitude: ${marker[0]}