将 Google Maps V3 标记的拖动限制为折线 [英] Confine dragging of Google Maps V3 Marker to Polyline

查看:26
本文介绍了将 Google Maps V3 标记的拖动限制为折线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've created a Google Map and have drawn a polyline on it. I've then added a marker to the start of the polyine (same coords as the starting coords of the polyline).

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

What I'd like to be able to do, is grab and drag the marker but have it "stick" to the polyline such that you can only drag it along the polyline and not away or to the side of it.

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

Is it possible to confine a draggable marker to a path in GM V3? If not, can anyone think how this might be done? There's the possibility of snapping the marker to the nearest point on the path when the user drops it, but I'd prefer a smoother "drag along the path" effect.

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

Happy to have ArcGis suggestions too. Have not provided code as this is more of an in theory question.

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

Let me know if I need to explain further.

提前致谢

推荐答案

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

Ok so I have managed to solve this. It's not exactly elegant, and I'm sure it could be improved on but here's the general concept I've come up with:

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

I create an array of latlng points from a GPX file, but they only log points every 20s or so. That's not enough granularity for my purposes so what I did is I padded the array of points with about 10 points (on a linear line) between each pair of points logged by the gpx:

$.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);
        }
    }
});

现在我有了更精细的点数组,我用它来绘制折线.填充的多段线与没有填充的多段线看起来没有什么不同,因为所有附加点都位于现有点之间的线性乌鸦苍蝇"线上.

Now that I have a more refined array of points, I use this to plot a polyline. The padded polyline will look no different to a polyline drawn without the padding, as all of the additional points lie on a linear "as-the-crow-flies" line between the existing points.

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

现在我在行首添加一个可拖动标记:

Now I add a draggable marker at the start of the line:

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

剩下要做的就是控制此标记的拖动和拖动事件:

All that's left to do is control the drag and dragend events of this marker:

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));
});

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

Here we simply send the latLng of the marker to a function find_closest_point_on_path() whilst dragging and when the marker is dropped. We send the padded array of points as a path to search.

函数如下所示:

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];
}

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

What this function does (with the help of a degrees to radians function) is it finds the distance between the markers position and all of the points on the line. Then it finds the closest point to the marker and returns the coordinates for the very next closest point after that one. This way, when you drag or drop the marker it "snaps" to the next point (rather than getting stuck in one spot).

工作JS小提琴如下:

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

尚未进行跨浏览器测试.使用 Chrome 最新版本.

Have not cross-browser tested. Working in Chrome latest version.

这篇关于将 Google Maps V3 标记的拖动限制为折线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆