根据提供的地址获取 Leaflet 的纬度和经度

28
在我的项目中,我正在使用leaflet来显示点位。
我从数据库中获取地址并想要为该特定地址显示点位。
我还没有找到任何能根据提供的地址给我纬度和经度的东西。
有人能帮我解决这个问题吗?
4个回答

31

如果您想使用OpenStreetmaps,请直接发出请求(使用jquery):

    $.get(location.protocol + '//nominatim.openstreetmap.org/search?format=json&q='+address, function(data){
       console.log(data);
    });
您将获得包含(不仅限于)纬度和经度的JSON对象。

这是免费的吗?请求次数没有限制吗? - Alauddin Afif Cassandra
此地址未找到。 - Sandeep Sherpur

18
没有额外插件的解决方案。只使用Leaflet和纯JavaScript。拖动标记或输入地址可获取坐标。如果您在Nominatim请求方面遇到问题,请将https更改为http。 演示在此处:http://yellowthailand.com/leafletgeo.html

<html>
<head>
<title>Leaflet Address Lookup and Coordinates</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"></script>
<style type="text/css">
html, body { width:100%;padding:0;margin:0; }
.container { width:95%;max-width:980px;padding:1% 2%;margin:0 auto }
#lat, #lon { text-align:right }
#map { width:100%;height:50%;padding:0;margin:0; }
.address { cursor:pointer }
.address:hover { color:#AA0000;text-decoration:underline }
</style>
</head>
<body>
<div class="container">

<b>Coordinates</b>
<form>
<input type="text" name="lat" id="lat" size=12 value="">
<input type="text" name="lon" id="lon" size=12 value="">
</form>

<b>Address Lookup</b>
<div id="search">
<input type="text" name="addr" value="" id="addr" size="58" />
<button type="button" onclick="addr_search();">Search</button>
<div id="results"></div>
</div>

<br />

<div id="map"></div>

</div>

<script type="text/javascript">

// New York
var startlat = 40.75637123;
var startlon = -73.98545321;

var options = {
 center: [startlat, startlon],
 zoom: 9
}

document.getElementById('lat').value = startlat;
document.getElementById('lon').value = startlon;

var map = L.map('map', options);
var nzoom = 12;

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: 'OSM'}).addTo(map);

var myMarker = L.marker([startlat, startlon], {title: "Coordinates", alt: "Coordinates", draggable: true}).addTo(map).on('dragend', function() {
 var lat = myMarker.getLatLng().lat.toFixed(8);
 var lon = myMarker.getLatLng().lng.toFixed(8);
 var czoom = map.getZoom();
 if(czoom < 18) { nzoom = czoom + 2; }
 if(nzoom > 18) { nzoom = 18; }
 if(czoom != 18) { map.setView([lat,lon], nzoom); } else { map.setView([lat,lon]); }
 document.getElementById('lat').value = lat;
 document.getElementById('lon').value = lon;
 myMarker.bindPopup("Lat " + lat + "<br />Lon " + lon).openPopup();
});

function chooseAddr(lat1, lng1)
{
 myMarker.closePopup();
 map.setView([lat1, lng1],18);
 myMarker.setLatLng([lat1, lng1]);
 lat = lat1.toFixed(8);
 lon = lng1.toFixed(8);
 document.getElementById('lat').value = lat;
 document.getElementById('lon').value = lon;
 myMarker.bindPopup("Lat " + lat + "<br />Lon " + lon).openPopup();
}

function myFunction(arr)
{
 var out = "<br />";
 var i;

 if(arr.length > 0)
 {
  for(i = 0; i < arr.length; i++)
  {
   out += "<div class='address' title='Show Location and Coordinates' onclick='chooseAddr(" + arr[i].lat + ", " + arr[i].lon + ");return false;'>" + arr[i].display_name + "</div>";
  }
  document.getElementById('results').innerHTML = out;
 }
 else
 {
  document.getElementById('results').innerHTML = "Sorry, no results...";
 }

}

function addr_search()
{
 var inp = document.getElementById("addr");
 var xmlhttp = new XMLHttpRequest();
 var url = "https://nominatim.openstreetmap.org/search?format=json&limit=3&q=" + inp.value;
 xmlhttp.onreadystatechange = function()
 {
   if (this.readyState == 4 && this.status == 200)
   {
    var myArr = JSON.parse(this.responseText);
    myFunction(myArr);
   }
 };
 xmlhttp.open("GET", url, true);
 xmlhttp.send();
}

</script>

</body>
</html>


15

已经为Leaflet开发了一个很棒的地理编码器。

https://github.com/smeijer/L.GeoSearch

您可以轻松使用结果,例如:

map.on('geosearch_showlocation', function (result) {
    L.marker([result.x, result.y]).addTo(map)
});

1
我想传递地址并在返回时获取纬度和经度。是否有任何可以实现这一功能的API? - vaibhav shah
1
正确。这就是该插件的功能。您输入一个地址,它会找出该地址的地理坐标。在触发的事件数据中,您可以访问该地理数据。(上面是结果) - snkashis
4
如果您想绕过用户输入并直接使用代码完成,那也很简单。只需使用 control.geosearch('New York, NY') 即可。 - snkashis
你能提供一个例子吗? - vaibhav shah
@snkashis 你好。在版本3.2.1中,'geosearch_showlocation'仍然有效吗?如果不是的话,在最新版本中该怎么做呢?谢谢。 - Aldy
显示剩余3条评论

1

还有一种解决方案,不使用任何插件。我从Mongo DB读取数据,然后使用Javascript、Angular(不一定)和Leaflet库绘制标记,用于显示从Mongo DB获取的坐标。

HTML

仅显示leaflet div和onclick事件,在此事件中传递用户的日期和电子邮件。这些信息将传递给MongoDB,以获取给定时间范围内用户的纬度和经度集合。

<div class="map" leaflet [leafletOptions]="historicalOptions">
        <div *ngFor="let l of historicalLayers" [leafletLayer]="l"></div>
      </div>

<div class="col-lg-3 d-flex justify-content-center align-items-center">
          <button type="button" (click)="getHistoricalData(onDate,fromTime,toTime,user.email)" class="btn btn-primary p-4">
            Get Map
          </button>
        </div>

代码

ngOnInit() {

this.historicalOptions = {
  layers: [
    tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '...' }),
    this.heatmapLayer
  ],
  center: latLng(xxxxxxx, xxxxxxx),
  zoom: 16
};
}

public getHistoricalData(onDate: Date, fromTime: Date, toTime: Date, userEmail) {

this.historicalLayers = [];
this.apiService.getGPSLocations(fromDate.toISOString(), toDate.toISOString(), userEmail)
    .subscribe(data => {

      if (data && data.length) {

        const markerLayers = this.drawMarkerPlotline(data, 'blue');
        this.historicalLayers = markerLayers;

      }
    }
}

private drawMarkerPlotline(data, color) {
if (data) {
  let rawData;
  if (typeof data === 'string')
    rawData = JSON.parse(data);
  else
    rawData = data;
  const layers = [];
  if (rawData.length) {
    this.heatmapData.data = [];
    rawData.forEach((point, index) => {
      if (point && point.sensorValue && point.sensorValue.attr_lat && point.sensorValue.attr_lng) {
        const markerLayer = marker([point.sensorValue.attr_lat, point.sensorValue.attr_lng], {
          icon: icon({
            iconSize: [15, 15],
            iconAnchor: [7, 7],
            iconUrl: this.getIconPath(color)
          }),
          title: new Date(point.observationTimestamp).toLocaleString(),
        });
        markerLayer.userId = point.userAccount.userId;

        layers.push(markerLayer);

        this.heatmapData.data.push({
          lat: point.sensorValue.attr_lat,
          lng: point.sensorValue.attr_lng,
          // count: 1
        });
      }
    });
    this.heatmapLayer.setData(this.heatmapData);

    return [layerGroup(layers)];
  }
}
return null;
}

private getIconPath(color) {
let icon: string;
switch (color) {
  case 'green':
    icon = 'assets/green-circle.png'
    break;
  case 'orange':
    icon = 'assets/orange-circle.png'
    break;
  default:
    icon = 'assets/blue-circle.png'
    break;
}
return icon;
}

注意

代码片段直接来自我的示例应用程序。因此,根据您的需求进行必要的更改以适应您的需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接