javascript - 连接并扩展 Google map 上的多边形编辑功能

标签 javascript events google-maps-api-3

在我的用例中,我们允许用户在 map 上定义“区域”(多边形)。只需设置 editable: true 即可启用基本的多边形编辑功能,效果很好。但是,我需要一些额外的功能。

例如,当用户开始拖动一个顶点时,我想突出显示其他多边形上附近的顶点,如果用户拖动其中一个顶点,它将“捕捉”他们拖动到的顶点的纬度/经度与拖过的顶点相同。

有没有人成功地在编辑过程中插入了一些“额外”代码?是否有任何中间事件在我可以连接、解释和在 map 上绘制一些额外内容的顶点句柄上触发(拖动、鼠标移动等)?我希望有人能告诉我“哦,如果 polygon.obfuscatedVariable 已设置,这些是拖动 handle ,您可以在 polygon.obfuscatedVariable[3] 上监听 mousemove ,检索纬度/经度等。”

黑客和陪审团操纵的解决方案是可以接受的:由于内置编辑非常接近我想要的,我真的不想从头开始重新创建它。

最佳答案

我已经忘记了这个问题,但这是我们解决问题的方法。希望对您有所帮助!

简短版:

每当一个mousedown出现在形状上,检查它是否在顶点上,如果是,使用 elementFromPoint保存对实际 HTML 的引用 <div>表示顶点句柄。在随后的mousemovemouseup事件,你可以轮询这个 <div> 的屏幕位置并将其与 map 上其他点的位置进行比较。

长版:

我已经从我们的应用程序中提取了相关功能,因此您需要忽略我们的一些特定功能和对象等,但这确实显示了我们的工作“对齐点”实现。

首先,我们将进行像素到经纬度的转换,因此您需要在某处定义一个简单的叠加层(您总是需要一个叠加层来进行这些计算):

_this.editor.overlay = new g.maps.OverlayView();
_this.editor.overlay.draw = function () {};
_this.editor.overlay.setMap(This.map);

现在,只要我们在 map 上初始化了一个形状,我们就会添加一个 mousedown它的事件处理程序。

g.maps.event.addListener(_this.shape, 'mousedown', function (event) {
  if (event.vertex >= 0) {
    var pixel =  _this.editor.overlay.getProjection().fromLatLngToContainerPixel(_this.shape.getPath().getAt(event.vertex));
    var offset = _this.mapElement.offset();
    var handle = document.elementFromPoint(pixel.x + offset.left, pixel.y + offset.top);

    if (handle) {
      _this.dragHandle = $(handle);
      _this.snappablePoints = _this.editor.snappablePoints(_this);
    } else {
      _this.dragHandle = null;
      _this.snappablePoints = null;
    }
  }
});

(您会注意到对 snappablePoints 的调用,它只是一个内部实用程序函数,它收集所有对该点捕捉有效的点。我们在这里这样做是因为它会是一个昂贵的循环对每个 mousemove 执行。)

现在,在我们的形状中 mousemove听众,因为我们保存了对那个 <div> 的引用,我们可以轮询它的屏幕位置并将其与 map 上其他点的屏幕位置进行比较。如果一个点在某个像素范围内(我想我们的是 8 个像素),我们会保存它并悬停一个小图标告诉用户我们要捕捉。

g.maps.event.addListener(this.shape, 'mousemove', function (event) {
  var projection, pixel, pixel2, offset, dist, i;

  if (event.vertex >= 0 && this.dragHandle) {
    // If dragHandle is set and we're moving over a vertex, we must be dragging an
    // editable polygon point. 

    offset = this.editor.mapElement.offset();
    pixel = {
      x: this.dragHandle.offset().left - offset.left + this.dragHandle.width() / 2,
      y: this.dragHandle.offset().top - offset.top + this.dragHandle.height() / 2
    };

    // Search through all previously saved snappable points, looking for one within the snap radius.
    projection = this.editor.overlay.getProjection();
    this.snapToPoint = null;
    for(i = 0; i < this.snappablePoints.length; i++) {
      pixel2 = projection.fromLatLngToContainerPixel(this.snappablePoints[i]);
      dist = (pixel.x - pixel2.x) * (pixel.x - pixel2.x) + (pixel.y - pixel2.y) * (pixel.y - pixel2.y);

      if (dist <= SNAP_RADIUS) {
        this.snapToPoint = this.snappablePoints[i];
        $('#zone-editor #snapping').css('left', pixel.x + 10 + offset.left).css('top', pixel.y - 12 + offset.top).show();
        break;
      }
    }

    if (!this.snapToPoint) {
      $('#zone-editor #snapping').hide();
    }
  });

当用户停止移动鼠标时进行一点清理:

g.maps.event.addListener(this.shape, 'mouseup', function (event) {
  // Immediately clear dragHandle, so that everybody knows we aren't dragging any more.
  // We'll let the path updated event deal with any actual snapping or point saving.
  _this.dragHandle = null;
  $('#zone-editor #snapping').hide();
});

最后,我们实际上处理了“捕捉”,这实际上只是形状路径上事件监听器中的一小部分逻辑。

g.maps.event.addListener(this.shape.getPath(), 'set_at', function (index, element) {
  if (this.snapToPoint) {
    // The updated point was dragged by the user, and we have a snap-to point.
    // Overwrite the recently saved point and let another path update trigger.
    var point = this.snapToPoint;
    this.snapToPoint = null;
    this.shape.getPath().setAt(index, point);
  } else  {
    // Update our internal list of points and hit the server
    this.refreshPoints();
    this.save();
  };

  // Clear any junk variables whenever the path is updated
  this.dragHandle = null;
  this.snapToPoint = null;
  this.snappablePoints = null;
});

鳍。

关于javascript - 连接并扩展 Google map 上的多边形编辑功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15976373/

相关文章:

asp.net - GridView 事件说明

javascript - Roads API 使用 GeoJSON 捕捉到道路

javascript - 本地图设置了 'restriction' 选项时,map.fitBounds 的工作很奇怪

javascript - 网站加载页面导致错误

javascript - 停止网页滚动

javascript - 注入(inject)子元素时触发 jQuery mouseout

javascript - Google map v3 - 限制功能可以工作的区域

javascript 只能在 tumblr 上远程工作

javascript - 如何在 UWP webview 上注入(inject) JS?

javascript - Backbone : Reference events to parent object