Google Maps v3 - 删除多边形上的顶点

Posted

技术标签:

【中文标题】Google Maps v3 - 删除多边形上的顶点【英文标题】:Google Maps v3 - Delete vertex on Polygon 【发布时间】:2012-02-08 12:34:16 【问题描述】:

谷歌地图有绘图库来绘制折线和多边形和其他东西。

此功能的示例:http://gmaps-samples-v3.googlecode.com/svn-history/r282/trunk/drawing/drawing-tools.html

我希望在绘制和编辑多边形时能够删除路径上的一个点/顶点。 API 文档似乎没有暗示任何内容。

【问题讨论】:

链接失效了。 【参考方案1】:

这是当前一项未完成的功能请求(已获 Google 承认)issue 3760。

这是我的解决方案:http://jsbin.com/ajimur/10。它使用一个函数向传入的多边形添加一个删除按钮(在撤消按钮下方)。


另外,有人建议这种方法:right-click to delete closest vertex,它工作得很好,但在 UI 技巧上有些欠缺。我构建了链接中的代码来检查点击是否在节点内部(或在节点的 1 像素内) - 在 JSBin 中:http://jsbin.com/ajimur/。

编辑:正如Amr Bekhit 指出的那样 - 这种方法目前已被破坏,因为事件需要附加到多边形。

【讨论】:

您的演示页面适用于我在 FF、IE 和 Chrome 中,但不适用于似乎覆盖右键单击事件的 Opera。但是谢谢。 对 - Opera 在默认情况下允许脚本执行的操作可能有点刻薄。这有帮助吗:groups.google.com/a/googleproductforums.com/forum/… 听起来不像是专家交流或其他任何东西,但如果有帮助,请 +1 我! :) 我一直在使用“右键单击删除”的方法,它运行良好。然而,看起来最近的谷歌地图更新已经阻止了它的工作。我最初认为这是我的代码,但你的两个例子也停止工作了......烦人! 我在此处 (code.google.com/p/gmaps-api-issues/issues/detail?id=4112) 发布了有关此问题的信息,幸运的是,已收到回复。看起来编辑手柄现在会生成附加到多边形本身的点击事件。因此,为了修改答案中的两个示例,请将多边形的可点击属性更改为 true,并将右键单击事件侦听器附加到多边形,而不是地图。【参考方案2】:

Google 地图现在为从多边形或折线触发的事件提供“PolyMouseEvent”回调对象。

要建立在建议涉及右键单击的解决方案的其他答案的基础上,您只需在最新版本的 V3 API 中执行以下操作:

// this assumes `my_poly` is an normal google.maps.Polygon or Polyline
var deleteNode = function(mev) 
  if (mev.vertex != null) 
    my_poly.getPath().removeAt(mev.vertex);
  

google.maps.event.addListener(my_poly, 'rightclick', deleteNode);

您会注意到,不再需要任何关于我们是否靠近该点的复杂计算,因为 Google Maps API 现在会告诉我们我们点击了哪个顶点。

注意:这仅在折线/多边形处于编辑模式时有效。(此时您可能要删除的顶点可见。)

作为最后的想法,您可以考虑改用单击或双击事件。 “单击”足够聪明,不会在拖动时触发,但使用单击触发仍可能会让您的一些用户感到惊讶。

【讨论】:

你可以在this的回调中切换my_poly。我用click 保护了confirm 对话框...我认为用户不会猜测右键单击(上下文菜单)或双击(缩放),但单击是自然的。谢谢! 这不适用于具有多个路径的多边形,例如甜甜圈。有关正确处理多个路径的代码,请参阅我的答案。【参考方案3】:

我发现 Sean 的代码非常简单且很有帮助。当用户只剩下 3 个节点时,我只是添加了一个限制器来停止删除。没有它,用户只能进入一个节点,并且不能再编辑:

my_poly.addListener('rightclick', function(mev)
    if (mev.vertex != null && this.getPath().getLength() > 3) 
        this.getPath().removeAt(mev.vertex);
    
);

【讨论】:

剩下 2 个节点仍然可以,因为它们之间有一个褪色的节点来创建一个新节点。不过谢谢你的提示,我用了。 优雅的解决方案!需要进行一项更改。多边形在路径中有顶点+1 个点,因为它们需要一个额外的点来闭合多边形。所以把 3 改成 4。这对我有用。【参考方案4】:

只是想我会做出贡献,因为我也在寻找解决方案,这是我的实现:

if (m_event.hasOwnProperty('edge') && m_event.edge >= 0 &&
GeofenceService.polygon.getPath().getLength() > 3) 
    GeofenceService.polygon.getPath().removeAt(m_event.edge);
    return;


if (m_event.hasOwnProperty('vertex') && m_event.vertex >= 0 &&
GeofenceService.polygon.getPath().getLength() > 3) 
    GeofenceService.polygon.getPath().removeAt(m_event.vertex);
    return;

这允许处理顶点节点和边节点的删除,并通过检查路径长度 > 3 来始终保持三角形形成多边形的最小值。

【讨论】:

【参考方案5】:

我遇到了需要从包含多条路径的多边形中删除节点的情况。这是 Sean 和 Evil 代码的修改:

shape.addListener('rightclick', function(event)
  if(event.path != null && event.vertex != null)
    var path = this.getPaths().getAt(event.path);
    if(path.getLength() > 3)
      path.removeAt(event.vertex);
    
  
);

【讨论】:

谢谢!这是救命稻草(:【参考方案6】:

2020 年更新

Google 在他们的文档中提供了一个工作演示,演示了如何通过右键单击顶点以显示“删除”菜单来删除顶点或线上的点。

查看Deleting a Vertex

以及完整的代码(参见他们的Github repo);

function initialize() 
  const mapOptions = 
    zoom: 3,
    center: new google.maps.LatLng(0, -180),
    mapTypeId: "terrain",
  ;
  const map = new google.maps.Map(document.getElementById("map"), mapOptions);
  const flightPlanCoordinates = [
    new google.maps.LatLng(37.772323, -122.214897),
    new google.maps.LatLng(21.291982, -157.821856),
    new google.maps.LatLng(-18.142599, 178.431),
    new google.maps.LatLng(-27.46758, 153.027892),
  ];
  const flightPath = new google.maps.Polyline(
    path: flightPlanCoordinates,
    editable: true,
    strokeColor: "#FF0000",
    strokeOpacity: 1.0,
    strokeWeight: 2,
    map: map,
  );

  /**
   * A menu that lets a user delete a selected vertex of a path.
   */
  class DeleteMenu extends google.maps.OverlayView 
    constructor() 
      super();
      this.div_ = document.createElement("div");
      this.div_.className = "delete-menu";
      this.div_.innerHTML = "Delete";
      const menu = this;
      google.maps.event.addDomListener(this.div_, "click", () => 
        menu.removeVertex();
      );
    
    onAdd() 
      const deleteMenu = this;
      const map = this.getMap();
      this.getPanes().floatPane.appendChild(this.div_);
      // mousedown anywhere on the map except on the menu div will close the
      // menu.
      this.divListener_ = google.maps.event.addDomListener(
        map.getDiv(),
        "mousedown",
        (e) => 
          if (e.target != deleteMenu.div_) 
            deleteMenu.close();
          
        ,
        true
      );
    
    onRemove() 
      if (this.divListener_) 
        google.maps.event.removeListener(this.divListener_);
      
      this.div_.parentNode.removeChild(this.div_);
      // clean up
      this.set("position", null);
      this.set("path", null);
      this.set("vertex", null);
    
    close() 
      this.setMap(null);
    
    draw() 
      const position = this.get("position");
      const projection = this.getProjection();

      if (!position || !projection) 
        return;
      
      const point = projection.fromLatLngToDivPixel(position);
      this.div_.style.top = point.y + "px";
      this.div_.style.left = point.x + "px";
    
    /**
     * Opens the menu at a vertex of a given path.
     */
    open(map, path, vertex) 
      this.set("position", path.getAt(vertex));
      this.set("path", path);
      this.set("vertex", vertex);
      this.setMap(map);
      this.draw();
    
    /**
     * Deletes the vertex from the path.
     */
    removeVertex() 
      const path = this.get("path");
      const vertex = this.get("vertex");

      if (!path || vertex == undefined) 
        this.close();
        return;
      
      path.removeAt(vertex);
      this.close();
    
  
  const deleteMenu = new DeleteMenu();
  google.maps.event.addListener(flightPath, "rightclick", (e) => 
    // Check if click was on a vertex control point
    if (e.vertex == undefined) 
      return;
    
    deleteMenu.open(map, flightPath.getPath(), e.vertex);
  );

【讨论】:

以上是关于Google Maps v3 - 删除多边形上的顶点的主要内容,如果未能解决你的问题,请参考以下文章

在 Google Maps API v3 中缩放到 geojson 多边形边界

Google Maps v3:检查点是不是存在于多边形中

从 MySQL 数据库在 Google Maps API v3 上绘制多个多边形

Google MAPS API V3 --> 如何显示存储在我的 MYSQL 表中的所有多边形?

Google Maps Javascript API V3中的旋转标记

如何从 Google Maps v3 API 中删除带有 mysql 数据的标记?