计算地点之间的行驶距离

Agu*_*rez 6 html javascript php openstreetmap osrm

我已经设法使用 Maptiler API (OSMNames) 为表单输入提供自动完成功能(因为我发现 Google Maps API 更令人困惑)。

所以实际的问题来了,我想借助我创建的两个输入中的自动完成功能来获取我输入的两个地点之间的行驶距离。

我正在尝试使用OSRM(开源路由机) API来做到这一点

这是我当前的脚本:

<!--AUTOCOMPLETE-->
<script>
    var autocomplete = new kt.OsmNamesAutocomplete(
    'search1', 'https://geocoder.tilehosting.com/', '#My_Maptiler_API_Code');
</script>
<script>
    var autocomplete = new kt.OsmNamesAutocomplete(
    'search2', 'https://geocoder.tilehosting.com/', '#My_Maptiler_API_Code');
</script>

<!--GET INFO-->
<script>
    function loadXMLDoc() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("result").innerHTML =
            this.responseText;
        }

        if (this.readyState == 4 && this.status == 429) {
            document.getElementById("result").innerHTML =
            "Server overloaded, please try again later."
        }
    };
    xhttp.open("GET", "http://router.project-osrm.org/table/v1/driving/{longitude1},{latitude1};{longitude2},{latitude2}", true);
    xhttp.send();
    }
</script>
Run Code Online (Sandbox Code Playgroud)

首先inputs,我需要借助该函数获取地点的坐标autocomplete

目前,当用户单击列表中的建议位置之一时,只有该name项目会写入框中input。相反,我想获取写入的 GPS 坐标,而不是name,以便我可以使用它们发送 HTTP 请求(下一步)。

当我点击时正在写什么:

当我点击时正在写什么

我下一步需要什么:

下一步我需要什么

顺便说一句,我在其他相关问题中看到了一些邀请使用“ Nominatim ”的答案。正如我所说,我目前正在使用“ OSMNames ”,有什么区别吗?我应该更改我的地理编码器吗?

然后,我还需要在 HTTP GET 请求中获取这些坐标,如代码所示。

最后,我只想从OSRM 响应中获取其中一项,即距离。否则,我只会得到完整的回复。

我尽量避免将所有代码放在这里,因为我在阅读时发现它令人困惑,但如果您出于任何原因需要其余代码,请告诉我!

Ale*_*ber 0

我为您创建了一个JSFiddle 演示,它使用 Nominatim 来解析目标位置,并使用 OSRM 表服务来计算到它的距离:

使用 Nominatim 和 OSRM 的 Openstreetmap

我的印象是,现在很多地理编码器插件维护得不好,所以我只是使用 jQuery 调用 Nominatim,然后调用 OSRM 表服务:

'use strict';

function processOsrmReply(data) {
  console.log(data);

  if (data.code !== 'Ok') {
    $('#myHint').text('OSRM error code: ' + data.code);
    return;
  }

  $('#myHint').text('Distance: ' + data.distances);
}

function sendOsrmRequest(startLat, startLng, endLat, endLng) {

  var osrmUrl = 'https://router.project-osrm.org/table/v1/driving/' +
    parseFloat(startLng).toFixed(6) + ',' + parseFloat(startLat).toFixed(6) + ';' +
    parseFloat(endLng).toFixed(6) + ',' + parseFloat(endLat).toFixed(6);

  var osrmParams = {
    sources: 0,
    destinations: 1,
    annotations: 'distance'
  };

  $('#myHint').text('Calculating driving distance between places...');
  $.get(osrmUrl, osrmParams, processOsrmReply);
}

var startPosition = [51.4661, 7.2491];
var myMap = L.map('myMap').setView(startPosition, 13);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(myMap);

var startMarker = L.marker(startPosition)
  .bindPopup('Start: ' + startPosition)
  .addTo(myMap);

$('#myInput').autocomplete({
  source: function(request, response) {

    var nominatimUrl = 'https://nominatim.openstreetmap.org/search/';

    var nominatimParams = {
      q: request.term,
      format: 'json',
      addressdetails: 1,
      limit: 2,
      polygon_geojson: 1
    };

    $.get(nominatimUrl, nominatimParams, function(data) {
      console.log(data);

      if (data.length === 0) {
        $('#myHint').text('Nominatim returned nothing');
        return;
      }

      var autocompleteParams = data.map(n => {
        return {
          label: n.display_name,
          value: [n.lat, n.lon]
        }
      });

      response(autocompleteParams);
    });
  },
  minLength: 5,
  select: function(event, ui) {
    var finalPosition = ui.item.value;
    var finalMarker = L.marker(finalPosition)
      .bindPopup('Destination: ' + finalPosition)
      .addTo(myMap);

    var markerBounds = L.latLngBounds(startMarker.getLatLng(), finalMarker.getLatLng());
    myMap.flyToBounds(markerBounds);

    sendOsrmRequest(startPosition[0], startPosition[1], finalPosition[0], finalPosition[1]);
    return false;
  }
});
Run Code Online (Sandbox Code Playgroud)
html,
body {
  padding: 0;
  margin: 0;
}

#myMap {
  position: absolute;
  top: 4em;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 1;
}

#myWidget {
  position: absolute;
  z-index: 2;
}
Run Code Online (Sandbox Code Playgroud)
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet.min.css">
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/themes/redmond/jquery-ui.min.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet-src.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/jquery-ui.min.js"></script>

<div class="ui-widget ui-front" id="myWidget">
  <label>Enter destination: <input id="myInput"></label>

  <div id="myHint">Type in at least 5 letters!</div>
</div>

<div id="myMap"></div>
Run Code Online (Sandbox Code Playgroud)

为了使演示代码简短,我将起始位置硬编码为我的家乡城市。

您可以添加第二个 jQuery UI 自动完成输入字段来改进这一点。

建议的解决方案不需要任何 API 密钥或付款,并且我的示例代码的许可证是:公共域。

如果您计划在生产中运行它,您应该安装您自己的 osrm-backend 和 Nominatim 实例。