Home > Net >  Google Maps Marker (calculated with epolys.js) not on polyline if zoom
Google Maps Marker (calculated with epolys.js) not on polyline if zoom

Time:01-27

My script shows a polyline between several markers. An additional marker (green circle) should visualize the distance already travelled.

The script works, but on high zoom-levels (12-15) the marker for the distance travelled do not "sit" on the polyline anymore, but many meters away. (see screengrab) The markers position is calculated with GetPointAtDistance from the Epolys.js-script.

See demo here: screenshot of resulting map

code snippet:

// initialise map
function initMap() {
  var options = {
    center: {
      lat: 51.69869842676892,
      lng: 8.188009802432369
    },
    zoom: 14,
    mapId: '1ab596deb8cb9da8',
    mapTypeControl: false,
    streetViewControl: false,
    fullscreenControlOptions: {
      position: google.maps.ControlPosition.RIGHT_BOTTOM
    },
  }
  var map = new google.maps.Map(document.getElementById('map'), options);

  google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
    var EarthRadiusMeters = 6378137.0; // meters
    var lat1 = this.lat();
    var lon1 = this.lng();
    var lat2 = newLatLng.lat();
    var lon2 = newLatLng.lng();
    var dLat = (lat2 - lat1) * Math.PI / 180;
    var dLon = (lon2 - lon1) * Math.PI / 180;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2)  
      Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
      Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = EarthRadiusMeters * c;
    return d;
  }

  google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
    // some awkward special cases
    if (metres == 0) return this.getPath().getAt(0);
    if (metres < 0) return null;
    if (this.getPath().getLength() < 2) return null;
    var dist = 0;
    var olddist = 0;
    for (var i = 1;
      (i < this.getPath().getLength() && dist < metres); i  ) {
      olddist = dist;
      dist  = this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
    }
    if (dist < metres) {
      return null;
    }
    var p1 = this.getPath().getAt(i - 2);
    var p2 = this.getPath().getAt(i - 1);
    var m = (metres - olddist) / (dist - olddist);
    // updated to use the geometry library function
    return google.maps.geometry.spherical.interpolate(p1, p2, m);
  }


  // Define a symbol using SVG path notation, with an opacity of 1.
  const dashedLine = {
    path: "M 0,-1 0,1",
    strokeOpacity: 1,
    scale: 8,
  };

  var markerCoordinates = [{
      lat: 51.17230192226146,
      lng: 7.005455256203302
    },
    {
      lat: 52.017106436819546,
      lng: 8.903316299753124
    },
    {
      lat: 52.1521613855702,
      lng: 9.972045956234473
    },
    {
      lat: 52.12123086563482,
      lng: 11.627830412053509
    },
    {
      lat: 53.6301544474316,
      lng: 11.415718027446243
    },
    {
      lat: 54.08291262244958,
      lng: 12.191652169789096
    },
    {
      lat: 54.3141629859056,
      lng: 13.097095856304708
    }
  ]

  // create markers
  for (i = 0; i < markerCoordinates.length; i  ) {
    marker = new google.maps.Marker({
      position: new google.maps.LatLng(markerCoordinates[i]['lat'], markerCoordinates[i]['lng']),
      map: map,
      optimized: true,
    });
  }

  // create polylines
  const stepsRoute = new google.maps.Polyline({
    path: markerCoordinates,
    geodesic: true,
    strokeColor: "#c5d899",
    strokeOpacity: 0.2,
    icons: [{
      icon: dashedLine,
      offset: "0",
      repeat: "35px",
    }, ]
  });
  stepsRoute.setMap(map);

  var polylineLength = google.maps.geometry.spherical.computeLength(stepsRoute.getPath());
  var groupPosition = stepsRoute.GetPointAtDistance(100600);

  // add marker at position of the group
  var positionMarker = new google.maps.Marker({
    map: map,
    position: groupPosition,
    icon: {
      path: google.maps.SymbolPath.CIRCLE,
      scale: 10,
      fillOpacity: 1,
      strokeWeight: 2,
      fillColor: '#5384ED',
      strokeColor: '#ffffff',
    },
  });

  var positionMarker = new google.maps.Marker({
    map: map,
    position: groupPosition,
  });
};
/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */

#map {
  height: 100%;
}


/* 
 * Optional: Makes the sample page fill the window. 
 */

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<!DOCTYPE html>
<html>

<head>
  <title>Directions Service</title>
  <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
  <!-- jsFiddle will insert css and js -->
</head>

<body>
  <div id="map"></div>

  <!-- 
      The `defer` attribute causes the callback 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
      with https://www.npmjs.com/package/@googlemaps/js-api-loader.
      -->
  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=geometry" defer></script>
</body>

</html>

  • Related