Google使用固定数量的点映射用户可编辑的多边形?

时间:2012-04-04 14:31:45

标签: javascript google-maps geocoding

好的,这是我的问题,我会用图片来说明它更容易。 Google maps editable hexagon

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

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

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

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

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

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

4 个答案:

答案 0 :(得分:4)

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

到目前为止,我发现的唯一解决方案是在绘制多边形后手动隐藏手柄。这里的问题是句柄没有任何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);

答案 1 :(得分:4)

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

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

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

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 :(得分:2)

作为@ 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();

    }

});

答案 3 :(得分:1)

我刚刚为此创建了一个替代解决方案,而无需摆弄 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