限制将Google Maps V3标记拖动到折线

Bra*_*row 13 arcgis draggable google-maps-markers google-polyline

我创建了一个谷歌地图并在其上绘制了折线.然后我在polyine的起点添加了一个标记(与折线的起始坐标相同的坐标).

我希望能够做的是抓住并拖动标记,但让它"粘"到折线上,这样你只能沿着折线拖动它而不是远离它或者它的侧面.

是否可以将可拖动标记限制在GM V3的路径中?如果没有,有谁能想到如何做到这一点?当用户放下标记时,有可能将标记捕捉到路径上最近的点,但我更喜欢更顺畅的"沿路径拖动"效果.

很高兴有ArcGis的建议.没有提供代码,因为这更像是一个理论问题.

如果我需要进一步解释,请告诉我.

提前致谢

Bra*_*row 13

好的,所以我设法解决了这个问题.它不是很优雅,我相信它可以改进,但这里是我提出的一般概念:

我从GPX文件创建一个latlng点数组,但它们每20秒左右只记录一次点.这对我的目的来说还不够粒度,所以我做的是用gpx记录的每对点之间用大约10个点(在线性线上)填充点阵列:

$.each(array_of_points_to_pad, function(key, pt) {
    var current_point = pt;//The current point
    var next_point = array_of_points_to_pad[key + 1];//The point immediately after the current point

    //Check that we're not on the last point 
    if (typeof next_point !== 'undefined') {
        //Get a 10th of the difference in latitude between current and next points
        var lat_incr = (next_point.lat() - current_point.lat()) / 10;

        //Get a 10th of the difference in longitude between current and next points
        var lng_incr = (next_point.lng() - current_point.lng()) / 10;

        //Add the current point to a new padded_points array
        padded_points.push(current_point);

        //Now add 10 additional points at lat_incr & lng_incr intervals between current and next points (in the new padded_points array)
        for (var i = 1; i <= 10; i++) {
            var new_pt = new google.maps.LatLng(current_point.lat() + (i * lat_incr), current_point.lng() + (i * lng_incr));
            padded_points.push(new_pt);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

现在我有一个更精确的点数组,我用它来绘制折线.填充折线看起来与没有填充的折线没有什么不同,因为所有附加点位于现有点之间的线性"如蝇 - 苍蝇"线上.

var line = new google.maps.Polyline({
    path: polyline_path_points_padded,
    strokeColor: '#ff0000',
    strokeOpacity: 1.0,
    strokeWeight: 2
});
line.setMap(map);
Run Code Online (Sandbox Code Playgroud)

现在我在行的开头添加一个可拖动的标记:

var latLng = new google.maps.LatLng(startlat,startlng);
var marker = new google.maps.Marker({
  position: latLng,
  map: map,
  draggable:true
});
Run Code Online (Sandbox Code Playgroud)

剩下要做的就是控制这个标记的拖拽和拖拽事件:

google.maps.event.addDomListener(marker,'dragend',function(e){
    marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});

google.maps.event.addDomListener(marker,'drag',function(e){
    marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});
Run Code Online (Sandbox Code Playgroud)

在这里,我们只需拖动标记的latLng到函数find_closest_point_on_path(),同时拖动标记.我们将填充的点数组作为搜索路径发送.

该函数如下所示:

function find_closest_point_on_path(marker_pt,path_pts){
    distances = new Array();
    distance_keys = new Array();
    $.each(path_pts,function(key, path_pt){
        var R = 6371; // km
        var dLat = (path_pt.lat()-marker_pt.lat()).toRad();
        var dLon = (path_pt.lng()-marker_pt.lng()).toRad();
        var lat1 = marker_pt.lat().toRad();
        var lat2 = path_pt.lat().toRad();

        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
        var d = R * c;
        //Store the key of the point on the path that matches this distance
        distance_keys[d] = key; 

    });
            //Return the latLng pt on the path for the second closest point 
    return path_pts[distance_keys[_.min(distances)]+1];
}
Run Code Online (Sandbox Code Playgroud)

这个函数的作用(借助于弧度函数的度数)是找到标记位置和线上所有点之间的距离.然后它找到距离标记最近的点,并返回该标记之后的下一个最近点的坐标.这样,当您拖放标记时,它会"捕捉"到下一个点(而不是卡在一个点上).

下面的工作JS小提琴:

http://jsfiddle.net/Z5GwW/4/

没有经过跨浏览器测试.使用Chrome最新版本.