[GIS] Moving marker along path/polyline using Leaflet API

leaflet

Trying to migrate from Googlemaps to Leaflet, some errors return in following functions.

Number.prototype.toRad = function() {
  return this * Math.PI / 180;
}
//
Number.prototype.toDeg = function() {
  return this * 180 / Math.PI;
}
// polyline length calc
L.Polyline.prototype.m_len = function () {
  var distance = 0,  coords = null, coordsArray = this._latlngs;
  for (i = 0; i < coordsArray.length - 1; i++) {
    coords = coordsArray[i];
    distance += coords.distanceTo(coordsArray[i + 1]);
  }
  return distance;
}
//
function moveAlongPath(point, distance, index) {
  index = index || 0; // Set index to 0 by default.
  if (index < routePoints.length) {
    var poly = new L.Polyline([routePoints[index], routePoints[index + 1]]);
    // alert(JSON.stringify(poly, null, 4));
    var distanceToNextPoint = poly.m_len();
    if (distance <= distanceToNextPoint) {
      return routePoints[index].moveTowards(routePoints[index + 1], distance);
      // error: routePoints[index].moveTowards is not a function
    } else {
      var d_distance = distance - distanceToNextPoint;
      return moveAlongPath(routePoints, d_distance, (index + 1)); 
    }
  } else {
    return null;
  }
} // end moveAlongPath
/////////////////////////////////
L.LatLng.prototype.moveTowards = function(point, distance) {
  var lat1 = this.lat.toRad();
  var lon1 = this.lng.toRad();
  var lat2 = point.lat().toRad();
  var lon2 = point.lng().toRad();
  var dLon = (point.lng() - this.lng()).toRad();
  // Find the bearing from this point to the next.
  var brng = Math.atan2(Math.sin(dLon) * Math.cos(lat2),
                        Math.cos(lat1) * Math.sin(lat2) -
                        Math.sin(lat1) * Math.cos(lat2) *
                        Math.cos(dLon));
  var angDist = distance / 6371000 ; // 66371000 Earth's radius.
  // Calculate the destination point, given the source and bearing.
  lat2 = Math.asin(Math.sin(lat1) * Math.cos(angDist) +
                   Math.cos(lat1) * Math.sin(angDist) *
                   Math.cos(brng));
  lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(angDist) *
                           Math.cos(lat1),
                           Math.cos(angDist) - Math.sin(lat1) *
                           Math.sin(lat2));
  if (isNaN(lat2) || isNaN(lon2)) {return null; }
  return L.LatLng(lat2.toDeg(), lon2.toDeg());
} // end moveTowards
// LINESTRING COORDINATES KML FILE 
var routePoints  = <?php echo $coordstring;?>
var polycolor    = <?php echo $race_polyclr;?>
var stroke_w = 5;
var polyline = L.polyline(routePoints, {color: polycolor, weight: stroke_w});
map.addLayer(polyline)

Best Answer

If you're migrating from GMaps to Leaflet, then you should check the Leaflet plugin list before implementing any behaviour not included in the default Leaflet build.

In your particular case, you should try using Leaflet.AnimatedMarker instead of implementing your own animation routines. Let me quote from the README file of that plugin:

var line = L.polyline([[40.68510, -73.94136],[40.68576, -73.94149],[40.68649, -73.94165]]),
    animatedMarker = L.animatedMarker(line.getLatLngs());

map.addLayer(animatedMarker);