javascriptgoogle-mapsgoogle-maps-api-3

How to clear the polylines when the itinerary change?


I'm loading a page with a map and routes already loaded.

We can change the origin, destination and transportation mode with this form :

<div id="formulaire" class="box">

    <input id="start" type="text" value="$4DTEXT($vo_personne.origine)" class="input my-1">
    <input id="end" type="text" value="$4DTEXT($vo_personne.destination)" class="input my-1">
    
    <div class="select my-1">
    <select id="mode_transport">
        <option value="DRIVING">Voiture</option>
        <option value="TRANSIT">Transports</option>
    </select>
    </div>
    
    <input type="submit" value="Actualiser le trajet" class="button my-1">
    
</div>

When I'm changing something in the form, the map change, the routes too but I didn't find a way to clear the old routes (polylines) on the previous map.

This is my JS code

<script>

// onglets jquery UI
$( function() {
    $( "#tabs" ).tabs();
} );

// Google Maps
function initMap() {
    directionsRenderer = new google.maps.DirectionsRenderer({
        polylineOptions : { // works only on the active path
            strokeColor: '#0047b3',
            strokeOpacity: 1.0,
            strokeWeight: 7
        }
    });
    
    directionsService = new google.maps.DirectionsService();
    
    map = new google.maps.Map(document.getElementById("carte"), {
        zoom: 5,  
        center: { lat : 46.603354, lng: 1.888334}, // france
    });

    directionsRenderer.setMap(map);
    
    calculateAndDisplayRoute(directionsService, directionsRenderer);

    document.getElementById("mode_transport").addEventListener("change", () => {
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    }); 
    document.getElementById("start").addEventListener("change", () => {
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    }); 
    document.getElementById("end").addEventListener("change", () => {
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    });
    
}

function calculateAndDisplayRoute(directionsService, directionsRenderer) {
    
    start = document.getElementById("start").value;
    end = document.getElementById("end").value; 
    selectedMode = document.getElementById("mode_transport").value;
    
    directionsRenderer.setMap(map); 
    
    directionsRenderer.setPanel(document.getElementById("itineraire"));

    directionsRequest = {
        origin: start,
        destination: end,
        travelMode: google.maps.TravelMode[selectedMode],
        provideRouteAlternatives: true,
        optimizeWaypoints: true,
    };

    directionsService
        .route(directionsRequest)
        .then((response) => {
            directionsRenderer.setDirections(response);
            
        //  console.log (response);
        //  console.log (response.routes.length + ' routes');
        //  status = (response.status);

            if (status === 'OK') {
                // les routes trouvées
                for (var i = 0, len = response.routes.length; i < len; i++) {
                    new google.maps.DirectionsRenderer({
                        map: map,
                        directions: response,
                        routeIndex: i
                    });
                    
                    // route sélectionnée par défaut ?
                    // lui attribuer un ID ?
                    var polyline = response.routes[i] ;
                }   
                    
                console.log (polyline);
            }

        })
        .catch((e) => window.alert("Directions request failed due to " + e));
}

// création de la carte à l'ouverture de la page
window.initMap = initMap;

</script>

I'm a beginner and it's my first map, so I didn't find a solution to update the polylines.

The new ones are good but the oldest ones should be deleted or hidden.

I've tried to change the events listenners by adding polyline.remove() but it create this error : Uncaught (in promise) ReferenceError: polyLinePath is not defined

document.getElementById("mode_transport").addEventListener("change", () => {
        polyline.remove();
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    }); 
    document.getElementById("start").addEventListener("change", () => {
        polyline.remove();
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    }); 
    document.getElementById("end").addEventListener("change", () => {
        polyline.remove();
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    });

Solution

  • You need to keep references to the directionsRenderer objects you are using to display the routes.

    In the global scope:

    let renderer = [];
    

    Then when you create the renderers, push them onto that array:

    for (var i = 0, len = response.routes.length; i < len; i++) {
      renderer.push(new google.maps.DirectionsRenderer({
        map: map,
        directions: response,
        routeIndex: i
      }));
    }   
    

    Then to remove the routes from the map, set the map to null on those renderers:

    function removeOldRoutes() {
      for (var i=0; i < renderer.length; i++) {
        renderer[i].setMap(null);
      }
      renderer = [];
    }
    

    proof of concept fiddle

    code snippet

    let map;
    let renderer = [];
    // Google Maps
    function initMap() {
        directionsRenderer = new google.maps.DirectionsRenderer({
            polylineOptions : { // works only on the active path
                strokeColor: '#0047b3',
                strokeOpacity: 1.0,
                strokeWeight: 7
            }
        });
        
        directionsService = new google.maps.DirectionsService();
        
        map = new google.maps.Map(document.getElementById("carte"), {
            zoom: 5,  
            center: { lat : 46.603354, lng: 1.888334}, // france
        });
    
        directionsRenderer.setMap(map);
        
        calculateAndDisplayRoute(directionsService, directionsRenderer);
    
        document.getElementById("mode_transport").addEventListener("change", () => {
            removeOldRoutes()
            calculateAndDisplayRoute(directionsService, directionsRenderer);
        }); 
        document.getElementById("start").addEventListener("change", () => {
            removeOldRoutes()
            calculateAndDisplayRoute(directionsService, directionsRenderer);
        }); 
        document.getElementById("end").addEventListener("change", () => {
            removeOldRoutes()
            calculateAndDisplayRoute(directionsService, directionsRenderer);
        });
        
    }
    function removeOldRoutes() {
      for (var i=0; i < renderer.length; i++) {
        renderer[i].setMap(null);
      }
      renderer = [];
    }
    function calculateAndDisplayRoute(directionsService, directionsRenderer) {
        
        start = document.getElementById("start").value;
        end = document.getElementById("end").value; 
        selectedMode = document.getElementById("mode_transport").value;
        
        directionsRenderer.setMap(map); 
        
        directionsRenderer.setPanel(document.getElementById("itineraire"));
    
        directionsRequest = {
            origin: start,
            destination: end,
            travelMode: google.maps.TravelMode[selectedMode],
            provideRouteAlternatives: true,
            optimizeWaypoints: true,
        };
    
        directionsService
            .route(directionsRequest)
            .then((response) => {
                directionsRenderer.setDirections(response);
                
                console.log (response);
                console.log (response.routes.length + ' routes');
                status = (response.status);
    
                if (status === 'OK') {
                    // les routes trouvées
                    for (var i = 0, len = response.routes.length; i < len; i++) {
                        console.log("rendering route "+i);
                        renderer.push(new google.maps.DirectionsRenderer({
                            map: map,
                            directions: response,
                            routeIndex: i
                        }));
                    }   
                }
    
            })
            .catch((e) => window.alert("Directions request failed due to " + e));
    }
    
    // création de la carte à l'ouverture de la page
    window.initMap = initMap;
    /* 
     * Always set the map height explicitly to define the size of the div element
     * that contains the map. 
     */
    #carte {
      height: 80%;
    }
    
    /* 
     * Optional: Makes the sample page fill the window. 
     */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    <!doctype html>
    <html>
      <head>
        <title>StackSnippet</title>
      </head>
      <body>
        <div id="carte"></div>
    <div id="formulaire" class="box">
    
        <input id="start" type="text" value="Paris" class="input my-1">
        <input id="end" type="text" value="Marseille" class="input my-1">
        
        <div class="select my-1">
        <select id="mode_transport">
            <option value="DRIVING">Voiture</option>
            <option value="TRANSIT">Transports</option>
        </select>
        </div>
        
        <input type="submit" value="Actualiser le trajet" class="button my-1">
        
    </div>
        <!-- 
          The `defer` attribute causes the script to execute after the full HTML
          document has been parsed. For non-blocking uses, avoiding race conditions,
          and consistent behavior across browsers, consider loading using Promises. See
          https://developers.google.com/maps/documentation/javascript/load-maps-js-api
          for more information.
          -->
        <script
          src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=weekly"
          defer
        ></script>
      </body>
    </html>