Javascript 连接并扩展Google地图上的多边形编辑功能
在我的用例中,我们允许用户在地图上定义“区域”(多边形)。只需设置Javascript 连接并扩展Google地图上的多边形编辑功能,javascript,events,google-maps-api-3,Javascript,Events,Google Maps Api 3,在我的用例中,我们允许用户在地图上定义“区域”(多边形)。只需设置editable:true,即可启用基本多边形编辑功能。但是,我需要一些额外的功能 例如,当用户开始拖动顶点时,我想高亮显示其他多边形上的附近顶点,如果用户拖动其中一个,它将“捕捉”他们拖动的顶点的纬度/高度,使其与拖动的顶点相同 是否有人成功地在编辑过程中插入了一些“额外”代码?在那些顶点控制柄(拖动、鼠标移动等)上是否有触发的中间事件,我可以在地图上钩住、解释和绘制一些额外的东西?我希望有人能告诉我“哦,如果设置了polygo
editable:true
,即可启用基本多边形编辑功能。但是,我需要一些额外的功能
例如,当用户开始拖动顶点时,我想高亮显示其他多边形上的附近顶点,如果用户拖动其中一个,它将“捕捉”他们拖动的顶点的纬度/高度,使其与拖动的顶点相同
是否有人成功地在编辑过程中插入了一些“额外”代码?在那些顶点控制柄(拖动、鼠标移动等)上是否有触发的中间事件,我可以在地图上钩住、解释和绘制一些额外的东西?我希望有人能告诉我“哦,如果设置了polygon.obfuscatedVariable
,这些是拖动手柄,你可以在polygon.obfuscatedVariable[3]
上监听mousemove,检索lat/long等。”
黑客和陪审团操纵的解决方案是可以接受的:因为内置的编辑非常接近我想要的,我真的不想从头开始重新创建它。我已经忘记了这个问题,但这是我们解决问题的方法。希望这会有帮助 简短版本: 每当形状上出现
鼠标向下
时,请检查它是否在顶点上,如果在顶点上,请使用元素frompoint
保存对表示顶点控制柄的实际HTML
的引用。在随后的mousemove
和mouseup
事件中,您可以轮询此
的屏幕位置,并将其与地图上其他点的位置进行比较
长版本:
我已经从应用程序中删除了相关的函数,因此您需要忽略一些特定的函数和对象等,但这确实显示了我们正在工作的“snap-to-point”实现
首先,我们将进行像素到纬度的lng转换,因此您需要在某个地方定义一个简单的叠加(您总是需要一个来进行这些计算):
现在,只要我们在地图上初始化了一个形状,我们就会向它添加一个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
侦听器中,因为我们保存了对该
的引用,所以我们可以轮询其屏幕位置,并将其与地图上其他点的屏幕位置进行比较。如果一个点在某个像素范围内(我认为我们的是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.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;
});
Fin.我已经忘记了这个问题,但这是我们解决这个问题的方法。希望这会有帮助 简短版本: 每当形状上出现
鼠标向下
时,请检查它是否在顶点上,如果在顶点上,请使用元素frompoint
保存对表示顶点控制柄的实际HTML
的引用。在随后的mousemove
和mouseup
事件中,您可以轮询此
的屏幕位置,并将其与地图上其他点的位置进行比较
长版本:
我已经从应用程序中删除了相关的函数,因此您需要忽略一些特定的函数和对象等,但这确实显示了我们正在工作的“snap-to-point”实现
首先,我们将进行像素到纬度的lng转换,因此您需要在某个地方定义一个简单的叠加(您总是需要一个来进行这些计算):
现在,只要我们在地图上初始化了一个形状,我们就会向它添加一个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
侦听器中,因为我们保存了对该
的引用,所以我们可以轮询其屏幕位置,并将其与地图上其他点的屏幕位置进行比较。如果一个点在某个像素范围内(我认为我们的是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.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;
});
Fin.你最终是如何处理的?你最终是如何处理的?+1谢谢你-非常酷。。。我喜欢GMaps中的多边形选择器——它在GMaps之外可用吗?i、 e.我有一个需要多边形选择的热图应用程序,谷歌的实现是我发现的最有吸引力的(与滚动我自己的…)+1感谢这一点-非常酷。。。我喜欢GMaps中的多边形选择器——它在GMaps之外可用吗?i、 e.我有一个需要多边形选择的热图应用程序,谷歌的实现是我发现的最有吸引力的(与我自己的滚动…)