【问题标题】:Google maps user-editable polygon with fixed number of points?谷歌用固定数量的点映射用户可编辑的多边形?
【发布时间】:2012-04-18 06:55:05
【问题描述】:

好的,这是我的问题,我会放一张图片来说明它更容易。

我需要用户绘制一些多边形,代表覆盖区域。

多边形需要有固定数量的点(顶点),因为它稍后会进入处理算法,如果多边形可以包含很多点,那就真的很慢了。

无论如何,在我的示例中,我们坚持使用六边形(6 分)。
用户需要能够拖动多边形并对其进行修改,但不能更改点数。

我尝试为多边形设置editable: true 选项,它工作正常,但它给了我图片上显示的情况。它为每个点创建一个句柄,并在每个点之间的中间创建另一个句柄(半透明)。现在,如果用户移动该半透明点,它将向多边形添加另一个点(顶点),并在新创建的线的中间添加额外的两个手柄。这给了我们一个 7 点多边形。

最好的选择是移除那些半透明的手柄,这样用户就只能拖动多边形点,这样他就不会影响点的总数。

我可以使用谷歌地图可编辑选项来实现这一点吗?

【问题讨论】:

  • 你能提供一个jsfiddle的例子吗?
  • 我无法为您提供一个工作示例,因为我正在使用 gmap 的外部库(不是很重要,它只是一个包装器,gmap3.net)。这是代码jsfiddle.net/m4uvN/1。在你问为什么 setTimeout() :) 之前,回调不会在正确的时刻返回。它在地图中渲染之前返回多边形,所以我必须稍微延迟删除

标签: javascript google-maps geocoding


【解决方案1】:

实现您想要的另一种方法是放弃多边形的内置编辑能力并自己实现它。这更加强大和灵活。

首先,不要使多边形可编辑。接下来,为多边形的每个角制作一个标记。最后,使每个标记可拖动,并在其“拖动”事件上设置一个事件侦听器以更新多边形。

制作标记并添加事件监听器:

for (var i=0; i<coordinates.length; i++){
    marker_options.position = coordinates[i];
    var point = new google.maps.Marker(marker_options);

    google.maps.event.addListener(point, "drag", update_polygon_closure(polygon, i));
}

其中 update_polygon_closure 定义为:

function update_polygon_closure(polygon, i){
    return function(event){
       polygon.getPath().setAt(i, event.latLng); 
    }
}

完整代码在此处的 jsfiddle 中:https://jsfiddle.net/3L140cg3/16/

【讨论】:

【解决方案2】:

由于似乎没有人有更好的解决方案,我将我的解决方法标记为已接受,以防有人偶然发现同样的问题。不是很漂亮,但可以完成工作

到目前为止,我发现的唯一解决方案是在绘制多边形后手动隐藏句柄。这里的问题是句柄没有任何 CSS 类或 id,所以我必须隐藏所有不透明度为 0.5 的 div(句柄的不透明度)。它有效,但风险很大,考虑到其他东西可能具有相同的不透明度并且不需要隐藏。

// variables
var map, path, color;

polygon = new google.maps.Polygon({
    paths: path,
    strokeColor: color,
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: color,
    fillOpacity: 0.10,
    editable: true,
});
polygon.setMap(map);
setTimeout(function(){ map.find('div[style*=opacity: 0.5]').hide(); }, 50);

【讨论】:

  • 只是隐藏 0.5 不透明度的 div 会产生奇怪的后果。如果多边形是可编辑的,您仍然可以单击 div 应该在的位置并拖动。当你这样做时,这会产生另一个中点。隐藏父 div 可以避免这种副作用。 $('#multi_markers div[style*="opacity: 0.5"]').parent('div[style*="cursor: pointer"]').hide(); 这仍然是一个相当冒险的解决方案,但它也是我找到的唯一一个,所以谢谢。
  • 注意,谢谢。在撰写本文时,它没有这个问题
  • 这是迄今为止我找到的唯一答案。确实不完美,但总比没有好!但是你为什么不直接在 CSS 中这样做呢?
【解决方案3】:

作为对@zolakt 答案的轻微改进,您既可以隐藏多边形上的中点 div,也可以添加一个 mousedown 事件侦听器来跟踪单击中点的时间,以防止拖动和更改多边形:

// hide the midpoints (note that users can still click where the hidden midpoint
// divs are and drag to edit the polygon
$('#multi_markers div[style*="opacity: 0.5"]').hide();

// get the paths for the current polygon
var octopusPaths = HotelLib.octopusPolygon.getPaths();


// track when a polygon midpoint is clicked on
google.maps.event.addListener(HotelLib.octopusPolygon, 'mousedown', function(mdEvent) {


    // if a midpoint is clicked on, mdEvent.edge will have an integer value
    if(mdEvent.edge || (mdEvent.edge == 0)){

        // immediately reset the polygon to its former paths
        // effectively disabling the drag to edit functionality
        HotelLib.octopusPolygon.setPaths(octopusPaths);

        // hide the midpoints again since re-setting the polygon paths
        // will show the midpoints
        $('#multi_markers div[style*="opacity: 0.5"]').hide();

    }

});

【讨论】:

  • 聪明!谢谢
【解决方案4】:

我刚刚为此创建了一个替代解决方案,而无需摆弄setTimeout 或折线创建。这也是一个有点全球性的解决方案,因此您基本上可以将其放入任何使用 Google 地图的既定程序中。

我们将使用MutationObserver 观察这些中点节点何时出现在 DOM 上,然后立即隐藏它们。当某些内容设置为可编辑时,它们应该开始出现。

基本上只要在地图初始化后把它放在任何地方:

var editMidpointNodeObserver = new MutationObserver(function(list, observer)
{
    if($('#mapwrapper div[style*="opacity: 0.5"]').parent('div[style*="cursor: pointer"]').length > 0)
    {
        $('#mapwrapper div[style*="opacity: 0.5"]').parent('div[style*="cursor: pointer"]').remove();
    }
    
});

editMidpointNodeObserver.observe($('#mapwrapper')[0], { childList: true, subtree: true });

#mapwrapper 更改为您的 Google 地图包装元素的 id。我在这里使用 jQuery,因此 $('#mapwrapper')[0] 将 jQuery 对象转换为原生 DOM 对象。没有 jQuery 也应该可以工作,我假设你知道如何将它转换为 vanilla js。

我们也只是直接删除节点,因此无需担心用户会意外点击不可见的节点。

所有浏览器都应该支持MutationObserver:https://caniuse.com/mutationobserver

【讨论】:

    猜你喜欢
    • 2020-08-15
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2016-02-11
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多