【问题标题】:Google Maps API V3: Snapping to nodes of another polygonGoogle Maps API V3:捕捉到另一个多边形的节点
【发布时间】:2013-11-21 22:29:38
【问题描述】:

我正在绘制相邻且共享边界的多边形。查看下面的示例图像,如果我要为蒙大拿州绘制一个多边形,我希望能够单击 Idaho 多边形的节点以获取相同的边界部分,以确保边界不重叠或有孔。但是,节点不允许直接点击它们,如果我让节点不可见,那么精度会变差,我最终可能会在两个多边形之间出现孔洞或重叠。

有没有办法将绘图捕捉到现有多边形的节点?如果没有,是否至少有一种方法可以使我可以直接单击节点所在的位置?我已将多边形的属性设置为可编辑:false 和可点击:false,但多边形(和节点)的边界仍然不允许点击。

我没有在 API 中看到任何用于捕捉的文档。

【问题讨论】:

  • 找到距离鼠标点击最近的多边形顶点。
  • @geocodezip:谢谢。我认为最好的方法是使用谷歌地图的几何库。我会试试看。
  • 如果你为蒙大拿州画了一个粗略的边界,你可以移动这些点,它们会捕捉到爱达荷州的点。
  • 我喜欢this example by Wolfgang Pichler,捕捉到折线和顶点之间,但可能有用(允许您捕捉多边形边缘的任何位置,而不仅仅是顶点)。

标签: javascript google-maps google-maps-api-3


【解决方案1】:

PolySnapper:简单的多边形顶点捕捉。

我创建了这个 this github repo 和 complementary jsfiddle。

一个简短的例子可能如下所示:

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();

注意:按照设计,jsfiddle 上的西方形状未设置为snapable(见上文polygons 属性),因此只有东方形状会捕捉:)

//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>

【讨论】:

  • 完成后如何获得 PS.polygon() 的实际内容?
  • 我已经很多年没用过了,但据我回忆,PS.polygon() 返回一个 Google Maps Polygon 对象。因此,请参阅 Google Maps API Docs 如何获取多边形数据。您可以尝试.toString() 开始。
猜你喜欢
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 2014-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
相关资源
最近更新 更多