求助:利用Google Maps JavaScript API绘制LPR相机抓拍车辆路径
解决Google Maps基于LPR相机坐标绘制车辆行驶路径的问题
Hey Rodney, let's fix that path drawing issue you're having with your LPR camera data and Google Maps. Your current code does a great job placing the camera markers, but the route logic was missing key pieces to actually calculate and render the vehicle's path. Here's how to get it working properly:
问题分析
Your code had a few critical gaps preventing path rendering:
- The route request parameters were being reset every marker loop, so you couldn't accumulate waypoints
- You used incorrect syntax for defining waypoints (it needs to be an array, not a function call)
- You never utilized Google Maps'
DirectionsServiceto calculate the route orDirectionsRendererto draw it on the map
解决方案步骤
- Keep markers sorted by capture time: Your existing
markersarray is already ordered by when the license plate was captured, which is essential for drawing a logical path. - Initialize direction tools: Use
DirectionsServiceto fetch route data from Google's API, andDirectionsRendererto display that route on your map. - Build a proper route request: Treat the first camera as the origin, last as the destination, and all middle cameras as waypoints. For large datasets, you can split the path into smaller segments if you hit API waypoint limits.
修正后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>LPR Camera Vehicle Path</title> <style> #map{ height: 500px; width: 750px; } </style> </head> <body> <h1>LPR Camera Vehicle Path</h1> <div id="map"></div> <script> function initMap(){ // Map options var options = { zoom: 12, center: {lat:40.355048,lng:-79.835499} } // Initialize map var map = new google.maps.Map(document.getElementById('map'), options); // Set up direction services for route calculation and rendering const directionsService = new google.maps.DirectionsService(); const directionsRenderer = new google.maps.DirectionsRenderer({ map: map, suppressMarkers: true // Keep custom camera markers, hide default route markers }); // Array of camera markers (sorted by capture time) var markers = [ { coords:{lat:40.337629,lng:-79.808826}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelW.png', content:'<h1>LINCOLN WAY WEST @ 48 2017/12/22 17:49</h1>' }, { coords:{lat:40.337385,lng:-79.809023}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelS.png', content:'<h1>48 SOUTH @ LINCOLN WAY 2017/12/22 17:53</h1>' }, { coords:{lat:40.355048,lng:-79.835499}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelE.png', content:'<h1>Rt. 148 East @ Hartman 2017/12/22 20:14</h1>' }, { coords:{lat:40.384877,lng:-79.824477}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelW.png', content:'<h1>Rt.30 West @ Warren Dr. 2017/12/22 20:22</h1>' }, { coords:{lat:40.384488,lng:-79.824129}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelE.png', content:'<h1>Rt. 30 East @ Warren Dr. 2017/12/22 21:29</h1>' }, { coords:{lat:40.355285,lng:-79.834959}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelW.png', content:'<h1>Rt. 148 West @ Hartman 2017/12/22 21:38</h1>' }, { coords:{lat:40.355048,lng:-79.835499}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelE.png', content:'<h1>Rt. 148 East @ Hartman 2017/12/22 21:46</h1>' }, { coords:{lat:40.337385,lng:-79.809023}, iconImage:'http://52.15.229.165/nconf/google_images/cctv-32YelS.png', content:'<h1>48 SOUTH @ LINCOLN WAY 2017/12/22 22:19</h1>' } ]; // Add all custom camera markers to the map markers.forEach(markerProps => addMarker(markerProps)); // Function to create custom markers with info windows function addMarker(props){ var marker = new google.maps.Marker({ position: props.coords, map: map, icon: props.iconImage }); // Add clickable info window if content exists if(props.content){ var infoWindow = new google.maps.InfoWindow({ content: props.content }); marker.addListener('click', () => infoWindow.open(map, marker)); } } // Calculate and render the vehicle path function calculateAndDisplayRoute(service, renderer) { // Convert middle markers to waypoints (exclude first/last as origin/destination) const waypoints = markers.slice(1, -1).map(marker => ({ location: marker.coords, stopover: true })); const routeRequest = { origin: markers[0].coords, destination: markers[markers.length - 1].coords, waypoints: waypoints, travelMode: google.maps.TravelMode.DRIVING }; service.route(routeRequest, (result, status) => { if (status === 'OK') { renderer.setDirections(result); } else { window.alert(`Route request failed: ${status}`); } }); } // Trigger route calculation calculateAndDisplayRoute(directionsService, directionsRenderer); } </script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=JAVASCRIPTAPIKEY&callback=initMap"> </script> </body> </html>
关键改进说明
- Direction Services:
DirectionsServicehandles fetching turn-by-turn route data from Google, whileDirectionsRendererdraws the path directly on your map. - Waypoint Handling: Middle camera locations are converted to waypoints to ensure the route follows the vehicle's actual path through each camera.
- Custom Marker Preservation:
suppressMarkers: trueensures your custom camera icons stay visible instead of being replaced by default route markers. - Error Handling: Added a simple alert to help debug route request failures (e.g., API key issues or invalid coordinates).
注意事项
If you have more than 23 camera points (the free API waypoint limit), modify the code to draw the path in segments: loop through the markers array, and draw a separate route between each pair of adjacent cameras instead of using waypoints.
内容的提问来源于stack exchange,提问作者Rodney Howard
相关产品推荐
相关产品推荐

