18

I was looking for a solution to this problem on stackoverflow but since I couldn't find the accurate solution I ended up solving it myself and post it here, hope it help.

Google Maps provides you the Polyline feature, which based on a list of coordinates can draw a series of lines joining all of them.

You can draw a polyline with a single arrow with the following code:

     var allCoordinates = [
        new google.maps.LatLng(26.291, 148.027),
        new google.maps.LatLng(26.291, 150.027),
        new google.maps.LatLng(22.291, 153.027),
        new google.maps.LatLng(18.291, 153.027)
    ];

     var polyline = new google.maps.Polyline({
            path: allCoordinates,
            strokeColor: color,
            strokeOpacity: 1.0,
            strokeWeight: 2,
            geodesic: true,
            icons: [{
                icon: {path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW},
                offset: '100%'
            }]
        });

The problem here is that the arrow will be only drawn in the last segment as shown in the next picture, but sometimes the route could be not so straightforward and we need to add an arrow on every segment.

The attribute 'repeat' inside the icon definition could be another option but allows only to define a measure in pixels and that definelty won't match with every change of direction on the polyline.

PICTURE1

So, one way I found to achive this was to make several polylines, one per segment allowing in that case the arrow to be drawn on each one. This is the code:

     var allCoordinates = [
        new google.maps.LatLng(26.291, 148.027),
        new google.maps.LatLng(26.291, 150.027),
        new google.maps.LatLng(22.291, 153.027),
        new google.maps.LatLng(18.291, 153.027)
    ];

    for (var i = 0, n = allCoordinates.length; i < n; i++) {

        var coordinates = new Array();
        for (var j = i; j < i+2 && j < n; j++) {
            coordinates[j-i] = allCoordinates[j];
        }

        var polyline = new google.maps.Polyline({
            path: coordinates,
            strokeColor: color,
            strokeOpacity: 1.0,
            strokeWeight: 2,
            geodesic: true,
            icons: [{
                icon: {path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW},
                offset: '100%'
            }]
        });
        polyline.setMap(map);
        polylines.push(polyline);

    }

And this is the Picture:

PICTURE2

I hope this works for anyone who is looking for something like this!

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Martín C
  • 1,027
  • 1
  • 9
  • 13
  • I've been looking for a way to place arrows along a route. This route would be the path of a polyline drawn through Google Maps DirectionService (which gives you the route which goes through certains coordinates you have). The solution you offer here is good for a self drawn polyline, which has vertices well separated. But the polyline drawn by DirectionService may have vertices too close (for example the vertices used to draw a roundabout). In that case your wonderful solution is not valid. If anyone has a solution for the problem I talk about, I'd really like to hear about. – Andrew F. Jun 20 '16 at 17:41
  • The solution I explain is for drawing arrows all along the route. The solution you are looking for is to do this with the exception of preventing the arrow to be added for segments with very short width (vertices too close). Adapting the above algorithm is not so difficult, you should check the distance between every two coordinates (inside the "for") for each coordinate and if they are below your desired threshold, create a polyline without icon in that case, otherwise add the polyline with the current arrow icon. I hope it helps! – Martín C Jun 22 '16 at 15:02
  • I came across this question because [the arrow tag is being burninated](https://meta.stackoverflow.com/questions/340724/the-arrow-tag-is-in-the-process-of-being-burninated). Can you move the answer to your question into an answer post instead of having both the question and answer in the question? (And also remove the arrow tag while you're at it.) – BSMP Aug 14 '18 at 17:39

2 Answers2

17

There is a repeat property for the icon options object. The example of dashed lines from the Google Maps JS API shows a way to do this with repeating symbols on the line instead of creating new Polylines. In the context of your example, it would look something like this:

var allCoordinates = [
    new google.maps.LatLng(26.291, 148.027),
    new google.maps.LatLng(26.291, 150.027),
    new google.maps.LatLng(22.291, 153.027),
    new google.maps.LatLng(18.291, 153.027)
];

var polyline = new google.maps.Polyline({
    path: allCoordinates,
    strokeColor: color,
    strokeOpacity: 1.0,
    strokeWeight: 2,
    geodesic: true,
    icons: [{
        icon: {path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW},
        offset: '100%',
        repeat: '20px'
    }]
});
polyline.setMap(map);
polylines.push(polyline);

This creates arrows along the lines like so:

map

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
coderroggie
  • 870
  • 12
  • 25
3

Here is a version with a simpler loop and a custom symbol so you can resize and modify it as needed - the google.maps.SymbolPath.FORWARD_CLOSED_ARROW is a fixed size - the scale property doesn't affect it.

const drawLines = (map, maps, places) => {
  const arrow = {
    path: 'M 0,0 5,15 -5,15 0,0 z', // 0,0 is the tip of the arrow
    fillColor: 'red',
    fillOpacity: 1.0,
    strokeColor: 'red',
    strokeWeight: 1,
  };
  const newLines = [];
  for (let i = 0; i < places.length - 1; i++) {
    const line = new maps.Polyline({
      path: places.slice(i, i+2),
      strokeColor: '#FF0000',
      strokeOpacity: 1.0,
      strokeWeight: 2,
      icons: [{
        icon: arrow,
        offset: '100%',
      }]
    });
    line.setMap(map);
    newLines.push(line);
  }
}

map

Brian Burns
  • 20,575
  • 8
  • 83
  • 77