Pre-loading an editable drawingmanager polygon in Google Maps

10,917

I know this is a little older but I have been working on a similar scenario. Loading polygons from a database, allowing them to be editable, and allowing other polygons to be added to the map. There's probably better ways to do this but this is functional and hopefully gets someone else on the right track.

      var areas = ( <?php echo json_encode($areas);?> );
  var coords = ( <?php echo json_encode($coords);?> );

  var drawingManager;
  var selectedShape;
  var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
  var selectedColor;
  var colorButtons = {};

  // Saving vars
  var selectedShape;
  var contentString;
  var polygons = [];
  var newPolys = [];

  function clearSelection() {
    if (selectedShape) {
      selectedShape.setEditable(false);
      selectedShape = null;
    }
  }

  function setSelection(shape) {
    clearSelection();
    selectedShape = shape;
    shape.setEditable(true);
    selectColor(shape.get('fillColor') || shape.get('strokeColor'));
  }

  function deleteSelectedShape(e) {
    if (selectedShape) {
      selectedShape.setMap(null);
      for (i=0; i < polygons.length; i++) {   // Clear out the polygons entry
        if (selectedShape.getPath == polygons[i].getPath) {
            polygons.splice(i, 1);
        }
      }
    }
  }

  function selectColor(color) {
    selectedColor = color;
    for (var i = 0; i < colors.length; ++i) {
      var currColor = colors[i];
      colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
    }

    // Retrieves the current options from the drawing manager and replaces the
    // stroke or fill color as appropriate.
    var polylineOptions = drawingManager.get('polylineOptions');
    polylineOptions.strokeColor = color;
    drawingManager.set('polylineOptions', polylineOptions);

    var rectangleOptions = drawingManager.get('rectangleOptions');
    rectangleOptions.fillColor = color;
    drawingManager.set('rectangleOptions', rectangleOptions);

    var circleOptions = drawingManager.get('circleOptions');
    circleOptions.fillColor = color;
    drawingManager.set('circleOptions', circleOptions);

    var polygonOptions = drawingManager.get('polygonOptions');
    polygonOptions.fillColor = color;
    drawingManager.set('polygonOptions', polygonOptions);
  }

  function setSelectedShapeColor(color) {
    if (selectedShape) {
      if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
        selectedShape.set('strokeColor', color);
      } else {
        selectedShape.set('fillColor', color);
      }
    }
  }

  function makeColorButton(color) {
    var button = document.createElement('span');
    button.className = 'color-button';
    button.style.backgroundColor = color;
    google.maps.event.addDomListener(button, 'click', function() {
      selectColor(color);
      setSelectedShapeColor(color);
    });

    return button;
  }

   function buildColorPalette() {
     var colorPalette = document.getElementById('color-palette');
     for (var i = 0; i < colors.length; ++i) {
       var currColor = colors[i];
       var colorButton = makeColorButton(currColor);
       colorPalette.appendChild(colorButton);
       colorButtons[currColor] = colorButton;
     }
     selectColor(colors[0]);
   }

  function initialize() {
      var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 7,
      center: new google.maps.LatLng(40.2444, -111.6608),           // Utah default coords
      mapTypeId: google.maps.MapTypeId.Terrain,
      disableDefaultUI: true,
      zoomControl: true
    });

    var polyOptions = {
      strokeWeight: 0,
      fillOpacity: 0.45,
      editable: true
    };


    // Creates a drawing manager attached to the map that allows the user to draw
    // markers, lines, and shapes.
    drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControlOptions: {
        drawingModes: [google.maps.drawing.OverlayType.POLYGON]},
      markerOptions: {
        draggable: true
      },
      polylineOptions: {
        editable: true
      },
      rectangleOptions: polyOptions,
      circleOptions: polyOptions,
      polygonOptions: polyOptions,
      map: map
    });

    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
        if (e.type != google.maps.drawing.OverlayType.MARKER) {
        // Switch back to non-drawing mode after drawing a shape.
        drawingManager.setDrawingMode(null);
        // Add an event listener that selects the newly-drawn shape when the user
        // mouses down on it.
        var newShape = e.overlay;
        newShape.type = e.type;
        polygons.push(newShape);

        setSelection(newShape);


        google.maps.event.addListener(newShape, 'click', function() {
          setSelection(newShape);
        });

        google.maps.event.addListener(newShape, 'mouseup', function() {
          for (i=0; i < polygons.length; i++) {   // Clear out the old polygons entry
            if (newShape.getPath == polygons[i].getPath) {
                polygons.splice(i, 1);
            }
          }
          polygons.push(newShape);
        });
      }
    });


    // Clear the current selection when the drawing mode is changed, or when the
    // map is clicked.
    google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
    google.maps.event.addListener(map, 'click', clearSelection);
    google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);

    buildColorPalette();


   /* Load Shapes that were previously saved */
    for (var inc = 0, ii = areas.length; inc < ii; inc++) {
      var newCoords = [];
      for (var c = 0, cc = coords.length; c < cc; c++) {
          if (coords[c].polygon == areas[inc].polygon) {
            var point = coords[c];
            newCoords.push(new google.maps.LatLng(point.lat, point.lng));
          }
      }

      newPolys[inc] = new google.maps.Polygon({
        path: newCoords,
        strokeWeight: 0,
        fillColor: areas[inc].fillColor,
        fillOpacity: areas[inc].fillOpacity
      });
      newPolys[inc].setMap(map);
      polygons.push(newPolys[inc]);
      addNewPolys(newPolys[inc]);
    }


    function addNewPolys(newPoly) {
        google.maps.event.addListener(newPoly, 'click', function() {
            setSelection(newPoly);
        });
    }

  }

  google.maps.event.addDomListener(window, 'load', initialize);
Share:
10,917

Related videos on Youtube

Yev
Author by

Yev

Updated on September 15, 2022

Comments

  • Yev
    Yev over 1 year

    I'm writing an application that will allow users to draw geographical polygon "zones" using the Google Maps API and save them in a database. There can only be one zone per user so I'm limiting this by switching to the hand and hiding drawing tools on overlaycomplete. After overlaycomplete, I am able to hit save and it saves in my database just fine - so this bit works. Further, I am able to retrieve the polygon from the database and display it as an editable polygon on the map. The issues I am having though are:

    1. When trying to drag the points of the inserted polygon, they get "stuck" to the mouse and never release. My guess is some sort of mouseup issue?

    2. Despite a polygon already existing, I'm still able to draw another one. Should I just hide the drawing tools in the beginning if a polygon is being loaded from the db?

    3. How do I attach an event to the polygon being pulled from the database so I can capture its vertices coordinates?

    You can see my current code here: http://jsfiddle.net/FUUxz/ or below:

    JS:

                var map; // Global declaration of the map
                var iw = new google.maps.InfoWindow(); // Global declaration of the infowindow
                var lat_longs = new Array();
                var markers = new Array();
                var drawingManager;
                function initialize() {
    
                     var myLatlng = new google.maps.LatLng(40.9403762, -74.1318096);
                    var myOptions = {
                        zoom: 13,
                        center: myLatlng,
                        mapTypeId: google.maps.MapTypeId.ROADMAP}
                    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
                    drawingManager = new google.maps.drawing.DrawingManager({
                    drawingMode: google.maps.drawing.OverlayType.POLYGON,
                    drawingControl: true,
                    drawingControlOptions: {
                        position: google.maps.ControlPosition.TOP_CENTER,
                        drawingModes: [google.maps.drawing.OverlayType.POLYGON]
                    },
                            polygonOptions: {editable:true,fillColor:'#ff0000',strokeColor:'#ff0000',strokeWeight:2}
                });
                drawingManager.setMap(map);
    
                google.maps.event.addListener(drawingManager, "overlaycomplete", function(event) {
                    var newShape = event.overlay;
                    newShape.type = event.type;
                    if (event.type==google.maps.drawing.OverlayType.POLYGON) {
                            overlayClickListener(event.overlay);$('#polygon').val(event.overlay.getPath().getArray());drawingManager.setOptions({drawingMode:null,drawingControl:false});
                        }
    
                });
                    var polygon_plan_0 = [
                        new google.maps.LatLng(40.9534555976547, -74.0871620178223)
                        ,
                        new google.maps.LatLng(40.9410084152192, -74.0948867797852)
                        ,
                        new google.maps.LatLng(40.9411380854622, -74.1165161132812)
                        ,
                        new google.maps.LatLng(40.9490474888751, -74.1221809387207)
                        ,
                        new google.maps.LatLng(40.955140973234, -74.124584197998)
                        ,
                        new google.maps.LatLng(40.9604561066844, -74.1153144836426)
                        ,
                        new google.maps.LatLng(40.9534555976547, -74.0871620178223)
                        ];
                        lat_longs.push(new google.maps.LatLng(40.9534555976547, -74.0871620178223));
    
                        lat_longs.push(new google.maps.LatLng(40.9410084152192, -74.0948867797852));
    
                        lat_longs.push(new google.maps.LatLng(40.9411380854622, -74.1165161132812));
    
                        lat_longs.push(new google.maps.LatLng(40.9490474888751, -74.1221809387207));
    
                        lat_longs.push(new google.maps.LatLng(40.955140973234, -74.124584197998));
    
                        lat_longs.push(new google.maps.LatLng(40.9604561066844, -74.1153144836426));
    
                        lat_longs.push(new google.maps.LatLng(40.9534555976547, -74.0871620178223));
    
                var polygon_0 = new google.maps.Polygon({
                    path: polygon_plan_0,
    
                    strokeColor: "#ff0000",
                    strokeOpacity: 0.8,
                    strokeWeight: 2,
                    fillColor: "#ff0000",
                    fillOpacity: 0.3,
                    editable: true
                });
    
                polygon_0.setMap(map);
    
    
                google.maps.event.addListener(polygon_0, "mouseup", function(event) {
                    overlayClickListener(event.overlay);$('#polygon').val(event.overlay.getPath().getArray());drawingManager.setOptions({drawingMode:null,drawingControl:false});
                });
    
    
                }
    
    
            function createMarker(markerOptions) {
                var marker = new google.maps.Marker(markerOptions);
                markers.push(marker);
                lat_longs.push(marker.getPosition());
                return marker;
            }
    
    initialize();
    
    function overlayClickListener(overlay) {
        google.maps.event.addListener(overlay, "mouseup", function(event){
            $('#polygon').val(overlay.getPath().getArray());
        });
    }
    

    HTML:

    <div id="map_canvas" style="width:100%; height:450px;"></div>
    <form action="http://garbagedayreminder.com/test/save" method="post" accept-charset="utf-8" id="map_form">
    <input type="text" name="polygon" value="" id="polygon"  />
    <input type="submit" name="save" value="Save!" id="save"  />
    </form>