0

I'm trying to animate a icon over a polyline like in this example: https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/overlay-symbol-animate.

It works but I want to add my own PNG as the icon that is being animated. This is what I tried:

        var line = new google.maps.Polyline({
            path: [{ lat: 25.774266, lng: -80.193659 }, { lat: 25.83333, lng: 25.83333 - 77.8999964 }],
            icons: [{
                icon: CruiseShip //This is my .PNG file
            }],
            strokeColor: '#ffffff',
            strokeWeight: 1,
            map: map
        });

        function animateCircle(line) {
            var count = 0;
            window.setInterval(function () {
                count = (count + 1) % 200;

                var icons = line.get('icons');
                icons[0].offset = (count / 2) + '%';
                line.set('icons', icons);
            }, 20);
        }

Using the lineSymbol object like in the example does work. How can I add a .PNG file to the polyline instead of the lineSymbol? Couldn't find any documentation on this.

Falcobezet
  • 31
  • 5
  • related question: [Google Maps JavaScript API v3 Marker Animation Based Off Known Route](https://stackoverflow.com/questions/14510324/google-maps-javascript-api-v3-marker-animation-based-off-known-route) – geocodezip Dec 06 '19 at 17:28
  • [example](http://www.geocodezip.com/v3_animate_marker_xml.html), [example on polyline from KML](http://www.geocodezip.com/geoxml3_test/v3_geoxml3_kmltest_animateMarker_linkto.html?filename=http://www.geocodezip.com/JBU181_20110102_kml.xml) – geocodezip Dec 06 '19 at 17:35
  • related question: [Animating Multiple Markers](https://stackoverflow.com/questions/18245513/animating-multiple-markers) – geocodezip Dec 06 '19 at 17:37

1 Answers1

1

The way you are trying to animate the icon only works for SVG Symbols.

Mike Williams wrote an extension to the Google Maps Javascript API v2 (now deprecated and turned off) called epoly which contains the method .GetPointAtDistance, which can be used to update the position of a "normal" icon along a polyline.

There is a interpolate method in the google.maps.geometry.spherical library which interpolates between two points, but isn't very accurate for large scale features.

proof of concept fiddle

code snippet:

// This example creates a 2-pixel-wide red polyline showing the path of
// the first trans-Pacific flight between Oakland, CA, and Brisbane,
// Australia which was made by Charles Kingsford Smith.

function initMap() {
  updatePolylinePrototype();
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 3,
    center: {
      lat: 0,
      lng: -180
    },
    mapTypeId: 'terrain'
  });

  var line = new google.maps.Polyline({
    path: [{
      lat: 25.774266,
      lng: -80.193659
    }, {
      lat: 25.83333,
      lng: 25.83333 - 77.8999964
    }, {
      lat: 28.411413,
      lng: -16.5449611
    }],
    strokeColor: '#ffffff',
    strokeWeight: 1,
    map: map
  });
  var marker = new google.maps.Marker({
    icon: {
      url: "http://earth.google.com/images/kml-icons/track-directional/track-12.png",
      anchor: new google.maps.Point(12, 12),
      scaledSize: new google.maps.Size(24, 24),
    },
    position: line.getPath().getAt(0),
    map: map
  })

  var bounds = new google.maps.LatLngBounds();
  for (var i = 0; i < line.getPath().getLength(); i++) {
    bounds.extend(line.getPath().getAt(i));
  }
  map.fitBounds(bounds);
  animateShip(line, marker);
}

function animateShip(line, marker) {
  var count = 0;
  var lineDistance = 0;
  for (var i = 1; i < line.getPath().getLength(); i++) {
    lineDistance += google.maps.geometry.spherical.computeDistanceBetween(line.getPath().getAt(i - 1), line.getPath().getAt(i))
  }

  window.setInterval(function() {
    count = (count + 1) % 200;

    marker.setPosition(line.GetPointAtDistance(lineDistance - (lineDistance * count / 200)));
  }, 20);
}

function updatePolylinePrototype() {
  // === A method which returns a GLatLng of a point a given distance along the path ===
  // === Returns null if the path is shorter than the specified distance ===
  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 += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), 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);
    return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
  }
}
/* 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;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=geometry">
</script>
geocodezip
  • 158,664
  • 13
  • 220
  • 245