google-mapsgoogle-maps-api-3google-polyline

How to add Multiple Polylines using Google Map JS Api while using addListeners


I am trying to add multiple polylines to the following sample and if i do so it is drawing the latest polyline and removing the old one. I know it can be done while loading the map. I have to use the following logic as it is perfectly drawing the arc between markers.

var map;

var curvature = 0.5; // how curvy to make the arc

function init() {
  var Map = google.maps.Map,
    LatLng = google.maps.LatLng,
    LatLngBounds = google.maps.LatLngBounds,
    Marker = google.maps.Marker,
    Point = google.maps.Point;

  // This is the initial location of the points
  // (you can drag the markers around after the map loads)
  var pos1 = new LatLng(38.60971599083999, -105.42822913560047);
  var pos2 = new LatLng(31.549917555822212, -99.49938531446615);

  var bounds = new LatLngBounds();
  bounds.extend(pos1);
  bounds.extend(pos2);

  map = new Map(document.getElementById('map-canvas'), {
    center: bounds.getCenter(),
    zoom: 12
  });
  map.fitBounds(bounds);

  var markerP1 = new Marker({
    position: pos1,
    // draggable: true,
    map: map
  });
  var markerP2 = new Marker({
    position: pos2,
    // draggable: true,
    map: map
  });

  var curveMarker;

  function updateCurveMarker() {
    var pos1 = markerP1.getPosition(), // latlng
      pos2 = markerP2.getPosition(),
      projection = map.getProjection(),
      p1 = projection.fromLatLngToPoint(pos1), // xy
      p2 = projection.fromLatLngToPoint(pos2);

    // Calculate the arc.
    // To simplify the math, these points 
    // are all relative to p1:
    var e = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
      m = new Point(e.x / 2, e.y / 2), // midpoint
      o = new Point(e.y, -e.x), // orthogonal
      c = new Point( // curve control point
        m.x + curvature * o.x,
        m.y + curvature * o.y);

    var pathDef = 'M 0,0 ' +
      'q ' + c.x + ',' + c.y + ' ' + e.x + ',' + e.y;

    var zoom = map.getZoom(),
      scale = 1 / (Math.pow(2, -zoom));

    var symbol = {
      path: pathDef,
      scale: scale,
      strokeWeight: 1,
      fillColor: 'none'
    };
    if (!curveMarker) {
      curveMarker = new Marker({
        position: pos1,
        clickable: false,
        icon: symbol,
        zIndex: 0, // behind the other markers
        map: map
      });
    } else {
      curveMarker.setOptions({
        position: pos1,
        icon: symbol,
      });
    }
  }

  google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
  google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);
}

google.maps.event.addDomListener(window, 'load', init);
html, body, #map-canvas {
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry,places&key=YOUR_API_KEY"></script>
<div id="map-canvas" style="border: 2px solid #3872ac;"></div>

How to add multiple polylines by adapting to the curve logic above?


Solution

  • Encapsulate the functionality to make the curve in a function and call it for every curve you want to appear on the map:

    function createCurveMarker(marker1, marker2, map) {
    
      var curveMarker;
    
      function updateCurveMarker() {
        var pos1 = marker1.getPosition(), // latlng
          pos2 = marker2.getPosition(),
          projection = map.getProjection(),
          p1 = projection.fromLatLngToPoint(pos1), // xy
          p2 = projection.fromLatLngToPoint(pos2);
    
        // Calculate the arc.
        // To simplify the math, these points 
        // are all relative to p1:
        var e = new google.maps.Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
          m = new google.maps.Point(e.x / 2, e.y / 2), // midpoint
          o = new google.maps.Point(e.y, -e.x), // orthogonal
          c = new google.maps.Point( // curve control point
            m.x + curvature * o.x,
            m.y + curvature * o.y);
    
        var pathDef = 'M 0,0 ' +
          'q ' + c.x + ',' + c.y + ' ' + e.x + ',' + e.y;
    
        var zoom = map.getZoom(),
          scale = 1 / (Math.pow(2, -zoom));
    
        var symbol = {
          path: pathDef,
          scale: scale,
          strokeWeight: 1,
          fillColor: 'none'
        };
        if (!curveMarker) {
          curveMarker = new google.maps.Marker({
            position: pos1,
            clickable: false,
            icon: symbol,
            zIndex: 0, // behind the other markers
            map: map
          });
        } else {
          curveMarker.setOptions({
            position: pos1,
            icon: symbol,
          });
        }
      }
    
      google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
      google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);
    }
    

    screenshot of map with two curves on it

    working code snippet:

    var map;
    
    var curvature = 0.5; // how curvy to make the arc
    
    function init() {
      // This is the initial location of the points
      // (you can drag the markers around after the map loads)
      var pos1 = new google.maps.LatLng(38.60971599083999, -105.42822913560047);
      var pos2 = new google.maps.LatLng(31.549917555822212, -99.49938531446615);
    
      var bounds = new google.maps.LatLngBounds();
      bounds.extend(pos1);
      bounds.extend(pos2);
    
      map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: bounds.getCenter(),
        zoom: 12
      });
    
      var markerP1 = new google.maps.Marker({
        position: pos1,
        zIndex: 10,
        map: map
      });
      var markerP2 = new google.maps.Marker({
        position: pos2,
        zIndex: 10,
        map: map
      });
      createCurveMarker(markerP1, markerP2, map);
    
      var pos3 = new google.maps.LatLng(43.8041334, -120.5542012);
      var pos4 = new google.maps.LatLng(38.8026097, -116.419389);
    
      bounds.extend(pos3);
      bounds.extend(pos4);
      map.fitBounds(bounds);
    
      var markerP3 = new google.maps.Marker({
        position: pos3,
        zIndex: 10,
        map: map
      });
      var markerP4 = new google.maps.Marker({
        position: pos4,
        zIndex: 10,
        map: map
      });
      createCurveMarker(markerP3, markerP4, map);
    
    }
    
    google.maps.event.addDomListener(window, 'load', init);
    
    function createCurveMarker(marker1, marker2, map) {
    
      var curveMarker;
    
      function updateCurveMarker() {
        var pos1 = marker1.getPosition(), // latlng
          pos2 = marker2.getPosition(),
          projection = map.getProjection(),
          p1 = projection.fromLatLngToPoint(pos1), // xy
          p2 = projection.fromLatLngToPoint(pos2);
    
        // Calculate the arc.
        // To simplify the math, these points 
        // are all relative to p1:
        var e = new google.maps.Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
          m = new google.maps.Point(e.x / 2, e.y / 2), // midpoint
          o = new google.maps.Point(e.y, -e.x), // orthogonal
          c = new google.maps.Point( // curve control point
            m.x + curvature * o.x,
            m.y + curvature * o.y);
    
        var pathDef = 'M 0,0 ' +
          'q ' + c.x + ',' + c.y + ' ' + e.x + ',' + e.y;
    
        var zoom = map.getZoom(),
          scale = 1 / (Math.pow(2, -zoom));
    
        var symbol = {
          path: pathDef,
          scale: scale,
          strokeWeight: 1,
          fillColor: 'none'
        };
        if (!curveMarker) {
          curveMarker = new google.maps.Marker({
            position: pos1,
            clickable: false,
            icon: symbol,
            zIndex: 0, // behind the other markers
            map: map
          });
        } else {
          curveMarker.setOptions({
            position: pos1,
            icon: symbol,
          });
        }
      }
    
      google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
      google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);
    }
    html,
    body,
    #map-canvas {
      height: 100%;
      width: 100%;
      margin: 0px;
      padding: 0px
    }
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
    <div id="map-canvas" ></div>