Search code examples
google-mapsgoogle-roads-api

google maps roads api looping - how to stop


I've implemented the code seen at:

https://developers.google.com/maps/documentation/roads/inspector.

In each of the examples on this page, the marker animation loops.

How are you supposed to stop the looping so that the icon remains at the end point until more coordinates are fed to it, at which point I'll animate from the last gps coord to the newest gps coord which I just received?

I just don't want to see the course traveled over and over again.


Solution

  • To stop the animation, cancel the setInterval when the icon reaches the end of the polyline.

    function animateCircle(polyline) {
      var count = 0;
      // fallback icon if the poly has no icon to animate
      var defaultIcon = [
        {
          icon: lineSymbol,
          offset: '100%'
        }
      ];
      handle = window.setInterval(function() {
        if ((count+1) == 200)
           window.clearInterval(handle);
        count = (count + 1) % 200;
        var icons = polyline.get('icons') || defaultIcon;
        icons[0].offset = (count / 2) + '%';
        polyline.set('icons', icons);
      }, 20);
    }
    

    proof of concept fiddle

    code snippet:

    /**
     * Animate an icon along a polyline
     * @param {Object} polyline The line to animate the icon along
     */
    function animateCircle(polyline) {
      var count = 0;
      // fallback icon if the poly has no icon to animate
      var defaultIcon = [{
        icon: lineSymbol,
        offset: '100%'
      }];
      handle = window.setInterval(function() {
        // when reaches end of polyline
        if ((count + 1) == 200) {
          // cancel the interval timer
          window.clearInterval(handle);
          // hide the circle
          var icons = polyline.get('icons') || defaultIcon;
          icons[0].icon.strokeOpacity = 0;
          polyline.set('icons', icons);
        }
    
        count = (count + 1) % 200;
        var icons = polyline.get('icons') || defaultIcon;
        icons[0].offset = (count / 2) + '%';
        polyline.set('icons', icons);
      }, 20);
    }
    
    
    // Icons for markers
    var RED_MARKER = 'https://maps.google.com/mapfiles/ms/icons/red-dot.png';
    var GREEN_MARKER = 'https://maps.google.com/mapfiles/ms/icons/green-dot.png';
    var BLUE_MARKER = 'https://maps.google.com/mapfiles/ms/icons/blue-dot.png';
    var YELLOW_MARKER = 'https://maps.google.com/mapfiles/ms/icons/yellow-dot.png';
    
    // URL for places requests
    var PLACES_URL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=';
    
    // URL for Speed limits
    var SPEED_LIMIT_URL = 'https://roads.googleapis.com/v1/speedLimits';
    
    var coords;
    
    /**
     * Current Roads API threshold (subject to change without notice)
     * @const {number}
     */
    var DISTANCE_THRESHOLD_HIGH = 300;
    var DISTANCE_THRESHOLD_LOW = 200;
    
    /**
     * @type Array<ExtendedLatLng>
     */
    var originals = []; // the original input points, a list of ExtendedLatLng
    
    var interpolate = true;
    var map;
    var placesService;
    var originalCoordsLength;
    
    // Settingup Arrays
    var infoWindows = [];
    var markers = [];
    var placeIds = [];
    var polylines = [];
    var snappedCoordinates = [];
    var distPolylines = [];
    
    // Symbol that gets animated along the polyline
    var lineSymbol = {
      path: google.maps.SymbolPath.CIRCLE,
      scale: 8,
      strokeColor: '#005db5',
      strokeWidth: '#005db5'
    };
    
    // Initialize
    function initialize() {
      // Centre the map on Sydney
      var mapOptions = {
        center: {
          'lat': -33.870315,
          'lng': 151.196532
        },
        zoom: 16
      };
    
      // Map object
      map = new google.maps.Map(document.getElementById('map'), mapOptions);
    
      // Places object
      placesService = new google.maps.places.PlacesService(map);
    
      drawSnappedPolyline();
    
      // Draw the polyline for the snapToRoads API response
      // Call functions to add markers and infowindows for each snapped
      // point along the polyline.
      function drawSnappedPolyline(snappedCoords) {
        var snappedCoords = [{
            lat: -33.87031296432842,
            lng: 151.19649532278828,
            originalIndex: 0,
            interpolated: false
          },
          {
            lat: -33.8702971,
            lng: 151.1964966,
            interpolated: true
          },
          {
            lat: -33.8702971,
            lng: 151.1964966,
            interpolated: true
          },
          {
            lat: -33.8700888,
            lng: 151.19690029999998,
            interpolated: true
          },
          {
            lat: -33.8700888,
            lng: 151.19690029999998,
            interpolated: true
          },
          {
            lat: -33.869997,
            lng: 151.197091,
            interpolated: true
          },
          {
            lat: -33.8699822,
            lng: 151.1971317,
            interpolated: true
          },
          {
            lat: -33.8699669,
            lng: 151.1971912,
            interpolated: true
          },
          {
            lat: -33.8699669,
            lng: 151.1971912,
            interpolated: true
          },
          {
            lat: -33.869954,
            lng: 151.1972377,
            interpolated: true
          },
          {
            lat: -33.8699449,
            lng: 151.1972855,
            interpolated: true
          },
          {
            lat: -33.86994270100937,
            lng: 151.197353292079,
            originalIndex: 1,
            interpolated: false
          },
          {
            lat: -33.8699414,
            lng: 151.19739339999998,
            interpolated: true
          },
          {
            lat: -33.8699441,
            lng: 151.1974702,
            interpolated: true
          },
          {
            lat: -33.8699507,
            lng: 151.19755139999998,
            interpolated: true
          },
          {
            lat: -33.8699602,
            lng: 151.1976302,
            interpolated: true
          },
          {
            lat: -33.86997848255702,
            lng: 151.19772949764274,
            originalIndex: 2,
            interpolated: false
          },
          {
            lat: -33.869981300000006,
            lng: 151.19774479999998,
            interpolated: true
          },
          {
            lat: -33.8700129,
            lng: 151.1978469,
            interpolated: true
          },
          {
            lat: -33.8700129,
            lng: 151.1978469,
            interpolated: true
          },
          {
            lat: -33.8700458,
            lng: 151.1979242,
            interpolated: true
          },
          {
            lat: -33.8700834,
            lng: 151.1979993,
            interpolated: true
          },
          {
            lat: -33.8701059,
            lng: 151.1980374,
            interpolated: true
          },
          {
            lat: -33.870184300000005,
            lng: 151.1981381,
            interpolated: true
          },
          {
            lat: -33.8702143,
            lng: 151.1981743,
            interpolated: true
          },
          {
            lat: -33.8702143,
            lng: 151.1981743,
            interpolated: true
          },
          {
            lat: -33.8702902,
            lng: 151.19825269999998,
            interpolated: true
          },
          {
            lat: -33.87031617902999,
            lng: 151.19827540632983,
            originalIndex: 3,
            interpolated: false
          },
          {
            lat: -33.8703672,
            lng: 151.19832,
            interpolated: true
          },
          {
            lat: -33.870480199999996,
            lng: 151.19839969999998,
            interpolated: true
          },
          {
            lat: -33.870480199999996,
            lng: 151.19839969999998,
            interpolated: true
          },
          {
            lat: -33.8705388,
            lng: 151.1984269,
            interpolated: true
          },
          {
            lat: -33.87057888561142,
            lng: 151.19844125817298,
            originalIndex: 4,
            interpolated: false
          },
          {
            lat: -33.870625219935086,
            lng: 151.19845785457534,
            originalIndex: 5,
            interpolated: false
          },
          {
            lat: -33.8706823,
            lng: 151.1984783,
            interpolated: true
          },
          {
            lat: -33.8706823,
            lng: 151.1984783,
            interpolated: true
          },
          {
            lat: -33.870718800000006,
            lng: 151.1984865,
            interpolated: true
          },
          {
            lat: -33.8708181,
            lng: 151.19850399999999,
            interpolated: true
          },
          {
            lat: -33.8708644,
            lng: 151.1985081,
            interpolated: true
          },
          {
            lat: -33.870908899999996,
            lng: 151.1985078,
            interpolated: true
          },
          {
            lat: -33.87095031058638,
            lng: 151.19850565885983,
            originalIndex: 7,
            interpolated: false
          },
          {
            lat: -33.8709998,
            lng: 151.19850309999998,
            interpolated: true
          },
          {
            lat: -33.87103822739919,
            lng: 151.1984996185936,
            originalIndex: 8,
            interpolated: false
          },
          {
            lat: -33.8713497,
            lng: 151.1984714,
            interpolated: true
          },
          {
            lat: -33.8713497,
            lng: 151.1984714,
            interpolated: true
          },
          {
            lat: -33.8718054,
            lng: 151.1984326,
            interpolated: true
          },
          {
            lat: -33.8719381,
            lng: 151.1984352,
            interpolated: true
          },
          {
            lat: -33.87203169684805,
            lng: 151.198429447748,
            originalIndex: 9,
            interpolated: false
          }
        ];
        var snappedPolyline = new google.maps.Polyline({
          path: snappedCoords,
          strokeColor: '#005db5',
          strokeWeight: 6,
          icons: [{
            icon: lineSymbol,
            offset: '100%'
          }]
        });
    
        snappedPolyline.setMap(map);
        animateCircle(snappedPolyline);
    
        polylines.push(snappedPolyline);
    
        var placeIds = [
          "ChIJS6cYMjeuEmsRVxRklOwdF8o",
          "ChIJS6cYMjeuEmsRVxRklOwdF8o",
          "ChIJ-dDXMDeuEmsRSUxWOfxOpYA",
          "ChIJ-dDXMDeuEmsRSUxWOfxOpYA",
          "ChIJKVpuODeuEmsRjffu1J1v888",
          "ChIJKVpuODeuEmsRjffu1J1v888",
          "ChIJKVpuODeuEmsRjffu1J1v888",
          "ChIJKVpuODeuEmsRjffu1J1v888",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJR6yfRDeuEmsRhllVwX6TMJ8",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJrV1uWzeuEmsR2N5RA6d2SEE",
          "ChIJeUaSWTeuEmsRGB2FlgUyPzE",
          "ChIJeUaSWTeuEmsRGB2FlgUyPzE",
          "ChIJeUaSWTeuEmsRGB2FlgUyPzE",
          "ChIJeUaSWTeuEmsRGB2FlgUyPzE",
          "ChIJeUaSWTeuEmsRGB2FlgUyPzE",
          "ChIJOU6hVzeuEmsRlJsTGD1vpqU",
          "ChIJOU6hVzeuEmsRlJsTGD1vpqU",
          "ChIJOU6hVzeuEmsRlJsTGD1vpqU",
          "ChIJOU6hVzeuEmsRlJsTGD1vpqU",
          "ChIJOU6hVzeuEmsRlJsTGD1vpqU",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJmRMQVTeuEmsRUH-faYDgJs0",
          "ChIJ9SmzqTCuEmsRbkJlaklnr2s",
          "ChIJ9SmzqTCuEmsRbkJlaklnr2s",
          "ChIJ9SmzqTCuEmsRbkJlaklnr2s",
          "ChIJ9SmzqTCuEmsRbkJlaklnr2s"
        ];
        for (var i = 0; i < snappedCoords.length; i++) {
          var marker = addMarker(snappedCoords[i]);
        }
      }
    
    } // End init function
    
    // Call the initialize function once everything has loaded
    google.maps.event.addDomListener(window, 'load', initialize);
    
    
    /**
     * Add a marker to the map and check for special 'interpolated'
     * and 'unsnapped' properties to control which colour marker is used
     * @param {ExtendedLatLng} coords - Coords of where to add the marker
     * @return {!Object} marker - the marker object created
     */
    function addMarker(coords) {
      var marker = new google.maps.Marker({
        position: coords,
        title: coords.lat + ',' + coords.lng,
        map: map,
        opacity: 0.5,
        icon: RED_MARKER
      });
    
      // Coord should NEVER be interpolated AND unsnapped
      if (coords.interpolated) {
        marker.setIcon(BLUE_MARKER);
      } else if (!coords.related) {
        marker.setIcon(YELLOW_MARKER);
      } else if (coords.originalIndex != undefined) {
        marker.setIcon(RED_MARKER);
        addCorrespondence(coords, marker);
      } else {
        marker.setIcon({
          url: GREEN_MARKER,
          scaledSize: {
            width: 20,
            height: 20
          }
        });
        addCorrespondence(coords, marker);
      }
    
      // Make markers change opacity when the mouse scrubs across them
      marker.addListener('mouseover', function(mevt) {
        marker.setOpacity(1.0);
      });
      marker.addListener('mouseout', function(mevt) {
        marker.setOpacity(0.5);
      });
    
      coords.marker = marker; // Save a reference for easy access later
      markers.push(marker);
    
      return marker;
    }
    
    
    /**
     * Fit the map bounds to the current set of markers
     * @param {Array<Object>} markers Array of all map markers
     */
    function fitBounds(markers) {
      var bounds = new google.maps.LatLngBounds;
      for (var i = 0; i < markers.length; i++) {
        bounds.extend(markers[i].getPosition());
      }
      map.fitBounds(bounds);
    }
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
      font-family: Roboto, Noto, sans-serif;
    }
    
    #map {
      height: 500px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places,geometry">
    </script>
    <div id="map">
    </div>