简体   繁体   中英

Google Maps API V3: Snapping to nodes of another polygon

I am drawing polygons that are adjacent and whose borders are shared. Looking at the example image below, if I were to draw a polygon for Montana, I'd like to be able to click on the nodes of the Idaho polygon for the part of the border that is the same to ensure the borders don't overlap or have holes. However, the nodes don't allow clicks directly on them, and if I make the nodes invisible then the accuracy is worsened and I'll probably end up with holes or overlaps between the two polygons.

Is there a way to snap a drawing to a node of an existing polygon? If not, is there at least a way to make it so that I can click directly where the nodes are? I've set the polygon's properties to editable: false and clickable: false, but the boundary of the polygon (and the nodes) still disallows clicks.

I haven't seen any documentation in the API for snapping.

谷歌地图上的多边形

PolySnapper: easy polygon vertice snapping.

PolySnapper GIF演示

I created this this github repo and complementary jsfiddle .

A brief example might look like:

var PS = PolySnapper({
      map: map,
      threshold: 20,
      key: 'shift',
      keyRequired: true,
      polygons: polygons,
      polystyle: polystyle,
      hidePOI: true,
      onEnabled: function(){
        console.log("enabled")
      },
      onDisabled: function(){
        console.log("disabled")
      },
      onChange: function(){
        console.log("a point was added, removed, or moved")
      }
});

//first enable the manager (enter drawing mode)
PS.enable();

//user draws the polygon, point by point, snapping when necessary.
//now, retrieve the polygon from the manager.
the_poly = PS.polygon();

//and disable the manager (exit drawing mode and clean up poly).
//you should now use the_poly as a polygon reference
PS.disable();

Note: By design, the western shape on jsfiddle is not set to snapable (see above polygons property) so only the eastern shape will snap :)

 //the only global variable //SM will become the SnapManager instance. var SM = null; google.maps.event.addDomListener(window, "load", function () { //we will center the map here var vancouver = { lat: 49.269858, lng: -123.137283 } //granville island coordinates. //you should be fetching your coordinates from your server var granville_coords = [ {lat: 49.27158485202591, lng: -123.13729763031006}, {lat: 49.27277488695786, lng: -123.13691139221191}, {lat: 49.27316689217891, lng: -123.13613891601562}, {lat: 49.27319489243262, lng: -123.13474416732788}, {lat: 49.27248088099777, lng: -123.13384294509888}, {lat: 49.2696667352996, lng: -123.13049554824829}, {lat: 49.268546632648494,lng: -123.13055992126465}, {lat: 49.268350612069995,lng: -123.13066720962524}, {lat: 49.2684906268484, lng: -123.13146114349365}, {lat: 49.268546632648494,lng: -123.13249111175537}, {lat: 49.26888266611402, lng: -123.13347816467285}, {lat: 49.26889666745873, lng: -123.13401460647583}, {lat: 49.2706328034105, lng: -123.1368041038513 } ]; //coordinates of blocks just east of burrard. var burrard_coords = [ {lat: 49.267972570183545, lng: -123.145751953125}, {lat: 49.2679445669656, lng: -123.14085960388184}, {lat: 49.27032478374826, lng: -123.14077377319336}, {lat: 49.27138884351881, lng: -123.14176082611084}, {lat: 49.27309689147504, lng: -123.14356327056885}, {lat: 49.27267688516586, lng: -123.14467906951904}, {lat: 49.27152884967477, lng: -123.14553737640381}, {lat: 49.269834748503946, lng: -123.1459450721740} ]; //make the satellite view google map, center it in Vancouver. map = new google.maps.Map(document.getElementById("map_div"), { center: new google.maps.LatLng(vancouver.lat, vancouver.lng), zoom: 16, mapTypeId: google.maps.MapTypeId.HYBRID }); //this style is easier on the eyes than the default black. //BADASS and COFFEE hex to the rescue. var polystyle = { strokeColor: '#BADA55', strokeOpacity: 0.8, strokeWeight: 2, fillColor: '#C0FFEE', fillOpacity: 0.35 } //options for granville polygon. //SNAPABLE = TRUE var poly1_opts = $.extend({ paths: granville_coords, map: map, snapable: true }, polystyle); //options for burrard polygon //SNAPABLE not present (false) var poly2_opts = $.extend({ paths: burrard_coords, map: map }, polystyle); //let's make the polygons var granville = new google.maps.Polygon(poly1_opts); var burrard = new google.maps.Polygon(poly2_opts); /* For demo purposes, lets just put two gmaps Polys into the polygon array. For your application purposes, you would populate this array with all of the polygons you want to snap to - likely driven from the DB. */ polygons = [granville, burrard]; /* Now, we make the SnapManager. See http://stackoverflow.com/a/33338065/568884 for API Will be transferred to Github soon. */ SM = PolySnapper({ map: map, marker: new google.maps.Marker(), threshold: 20, keyRequired: false, polygons: polygons, polystyle: polystyle, hidePOI: true, onEnabled: function(){ console.log("enabled") }, onDisabled: function(){ console.log("disabled") } }); //add the buttons initial state on top of the map. renderCpanel(false); }); //when user clicks log poly button, pull the poly out of the manager and console.log it. $(document).on("click", "#query", function(){ console.log( SM.poly().getPath().getArray() ); }); //just a small render function to re-draw the buttons whenever the enabled state is flipped on and off. function renderCpanel(drawing){ var t = $("#control-panel").html(); var html = _.template(t, {drawing: drawing}); $("#cp-wrap").html(html); } //attach the click handlers to the button. #cp-wrap is never added or removed //from the DOM, so its safe to bind the listeners to it. $("#cp-wrap").on("click", "button", function(){ var action = $(this).data("action"); if (action == 'new') SM.enable(); else if(action == 'query') console.log( SM.polygon() ) else SM.disable(); renderCpanel( (action == 'new') ); }); 
 body { margin: 0; padding: 0; font: 12px sans-serif; } #cp-wrap{ position: absolute; top: 10px; left:120px; background-color:white; } #cp-wrap button{ font-size: 22px; } 
 <script src="https://rawgit.com/jordanarseno/polysnapper/master/polysnapper.js"></script> <script src="http://underscorejs.org/underscore-min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://maps.google.com/maps/api/js?.js"></script> <div style='position:relative;'> <div id="map_div" style="height: 600px; width:100%;"></div> <div id='cp-wrap'></div> </div> <script id='control-panel' type='text/template'> <% if(drawing) { %> <button data-action='cancel' >cancel</button> <button data-action='query' >log poly</button> <% } else { %> <button data-action='new' >new poly</button> <% } %> </script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM