Search code examples
google-maps-api-3google-polyline

Google Maps V3 Polyline : make it editable without center point(s)


I'm struggling with Google Maps Api V3 Polylines. It is possible with this API to create user-editable shapes, as this tutorial shows for the Rectangle shape. But when I do the same with a Polyline, I have a problem with the center of the segment.

In the Rectangle example, such a center point is used to extend the size of the rectangle's side. But in my Polyline, this point, when dragged, breaks the line onto two new lines. Thus, each of them gets a new center. As a consequence, instead of 2 points, I now have 5 points. And this is endless : everytime I click on a center point and I drag it, it creates new points.

Here is a part of my code :

var polyCoord = [
        new google.maps.LatLng(41.86, 8.73),
        new google.maps.LatLng(41.88, 8.75)
    ];

    // Polyline
    var pol = new google.maps.Polyline({
        path: polyCoord,
        editable: true
    });
    pol.setMap(map);

How can I make editable Polylines with only 2 points ? Thanks


Solution

  • Using the concept from this question: Avoiding vertex drag maps api v3

    1. Don't use editable polylines (those have the edit handle in the middle that you don't want).

    2. Bind a marker to each of the two vertices of the polyline, make those draggable.

    proof of concept fiddle

    code snippet:

    var map;
    
    function initialize() {
      map = new google.maps.Map(
        document.getElementById("map_canvas"), {
          center: new google.maps.LatLng(37.4419, -122.1419),
          zoom: 13,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });
      var polyCoord = [
        new google.maps.LatLng(41.86, 8.73),
        new google.maps.LatLng(41.88, 8.75)
      ];
      var bounds = new google.maps.LatLngBounds();
      bounds.extend(polyCoord[0]);
      bounds.extend(polyCoord[1]);
      map.fitBounds(bounds);
      // Polyline
      var pol = new google.maps.Polyline({
        path: polyCoord
      });
      pol.binder = new MVCArrayBinder(pol.getPath());
      var marker0 = new google.maps.Marker({
        position: event.latLng,
        title: '#0',
        map: map,
        icon: {
          url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
          size: new google.maps.Size(7, 7),
          anchor: new google.maps.Point(3.5, 3.5)
        },
        draggable: true
      });
      marker0.bindTo('position', pol.binder, (0).toString());
      var marker1 = new google.maps.Marker({
        position: event.latLng,
        title: '#1',
        map: map,
        icon: {
          url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
          size: new google.maps.Size(7, 7),
          anchor: new google.maps.Point(3.5, 3.5)
        },
        draggable: true
      });
      marker1.bindTo('position', pol.binder, (1).toString());
      pol.setMap(map);
    }
    google.maps.event.addDomListener(window, "load", initialize);
    
    /*
     * Use bindTo to allow dynamic drag of markers to refresh poly.
     */
    
    function MVCArrayBinder(mvcArray) {
      this.array_ = mvcArray;
    }
    MVCArrayBinder.prototype = new google.maps.MVCObject();
    MVCArrayBinder.prototype.get = function(key) {
      if (!isNaN(parseInt(key))) {
        return this.array_.getAt(parseInt(key));
      } else {
        this.array_.get(key);
      }
    }
    MVCArrayBinder.prototype.set = function(key, val) {
      if (!isNaN(parseInt(key))) {
        this.array_.setAt(parseInt(key), val);
      } else {
        this.array_.set(key, val);
      }
    }
    html,
    body,
    #map_canvas {
      height: 100%;
      width: 100%;
      margin: 0px;
      padding: 0px
    }
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
    <div id="map_canvas" style="border: 2px solid #3872ac; "></div>