使折线捕捉到传单中的道路
Posted
技术标签:
【中文标题】使折线捕捉到传单中的道路【英文标题】:Making polyline snap to roads in leaflet 【发布时间】:2016-04-05 09:01:14 【问题描述】:我正在从数据库中加载标记,然后在标记之间绘制一条折线。我正在使用折线来计算总距离,而不必计算从标记-a 到标记-b 到标记-c 的距离等等。
然而,我的距离并不准确,因为如果两个标记在弯曲的道路周围,多段线只是将它们连接起来,而不是沿着道路绘制。
我知道这在 Google Maps API 中是可能的,但使用限制不适合我,这就是我决定使用传单的原因。
我的标记相距不远,因为我的 GPS 设备每 10 秒发送一次位置。
我找到了leaflet-routing-machine 插件,我想知道是否可以使用它来使我的折线与道路对齐?
这就是我向地图添加标记的方式:
function getlocationsfromdb()
group.clearLayers();
latlngArray.length=0;
var deviceid = $("#selectid").val();
$.ajax(
type: "POST",
url: "functionhandlers/getlocations.php",
data: deviceid:deviceid,start:start,end:end,
dataType: 'json',
cache: false,
)
.success(function(response)
$('input').removeClass('error').next('.errormessage').html('');
if(!response.errors && response.result)
$.each(response.result, function( index, value)
var latlng = L.latLng(value[7], value[8]);
var marker = L.circleMarker(latlng,radius:2).addTo(group);
latlngArray.push(latlng);
);
var polyline = L.polyline(latlngArray, color: '#605ca8').addTo(group);
map.fitBounds(group.getBounds());
var distancetravelled=polyline.measuredDistance();
$("#distancetravelled").html(distancetravelled);
else
$.each(response.errors, function( index, value)
// add error classes
$('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
);
);
有人可以指点我正确的方向吗?
【问题讨论】:
【参考方案1】:这可以通过传单路由机轻松完成。您可以在初始化路由控制时将waypoints
设置为您的latlngArray
:
var control = L.Routing.control(
waypoints: latlngArray,
show: false,
waypointMode: 'snap',
createMarker: function()
).addTo(map);
这里,show: false
阻止控件显示在地图上,而空的 createMarker
函数会覆盖路由机器创建的默认标记,而不是什么都不做(尽管当我们移除控件时标记会被移除,这只是防止它们在找到路线时在屏幕上闪烁)。
您可以通过侦听routeselected
事件来提取路由机器结果的所有顶点,该事件将返回一个IRoute
object,其中包含路线的所有方向和几何形状。将.route.coordinates
放在一个新的L.polyline
对象中将保留路由,因此我们可以摆脱路由控制:
control.on('routeselected', function(e)
L.polyline(e.route.coordinates).addTo(group);
map.removeControl(control);
);
在您填充latlngArray
后立即将上述代码块放在您的.success
回调函数中应该会给您想要的路线。这是一个在工作中展示这个的小提琴:
http://fiddle.jshell.net/nathansnider/ygktexbj/
另外,如果您没有将路由控件用于其他任何事情,并且不想让它完全显示(在计算路由时可能仍会出现一个小的白色控件框),您可以简单地将其隐藏在 CSS :
.leaflet-routing-container
display:none;
【讨论】:
我意识到这个解决方案有点迂回,因为它创建了一个控件,然后一半的代码只是阻止该控件显示在地图上。虽然我怀疑有一种方法可以在不创建控件的情况下执行此操作,可能直接使用L.Routing.osrm
,但我无法从文档中完全弄清楚。
这太棒了!感谢您花时间向我详细解释,非常感谢 Nathan! :)
小提琴已经死了:(【参考方案2】:
我意识到这个解决方案有点迂回,因为它创建了一个控件,然后一半的代码只是阻止该控件显示在地图上
您实际上不必将其添加到地图中。此外,您可以直接攻击内部路由器的route
函数。
var routingControl = L.Routing.control(
waypointMode: 'snap'
);
然后
routingControl._router.route(latLngCoordinates, function(err, waypoints)
var a = waypoints;
);
小心,这是原始复制/粘贴: - 航点适合内部格式(检查它) - latLngCoordinates 必须是 lat:, lng: 格式 - 它可能需要一些清理,因为生成的 url 封装了一些很长的“提示”数据。
【讨论】:
以上是关于使折线捕捉到传单中的道路的主要内容,如果未能解决你的问题,请参考以下文章