最近有个需求,需要用到定位,本来打算用百度地图API定位,但是发现百度地图定位申请AppKey太麻烦了。因为是写的web端,百度地图定位API申请的Appkey需要网址过滤。索性就用高德定位了(有一说一,高德地图是真得劲)。话不多说,先讲解一下定位实现的一些需要注意的细节问题。
方法一 C#后端获取定位
首先,不管使用的是高德定位还是百度定位,都需要获取AppKey。下面先讲解高德定位APPKEY的获取。 用百度定位的,百度APPKEY获取方法自行百度。
1.打开高德地图Appkey申请网址:https://lbs.amap.com/,点击右上角控制台,然后进行登录和一系列的认证【进行个人认证就好,日配额5000次。如果定位的量大,再考虑走企业认证】。
如下:
认证完成后,进入高德地图控制台,创建应用分组:
然后创建AppKey:
这就是我们创建的AppKey:
我已经创建了一个,就直接用开头创建的那个做讲解。高德地图个人开发者每天的各种定位的配额5000次完全够用。
2.实战代码[发布网址必须是HTTPS,因为是web端,最好用谷歌浏览器,定位精度最高]:
html:
<button type="button" class="layui-btn" id="GPS">获取定位</button>
Js的前端代码:
<script type="text/javascript" scr="http://api.map.baidu.com/api?v=1.2"></script>
<script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script>
<script type="text/javascript">
//浏览器应该设置https,否则无响应
var vconsole = new VConsole();
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;
$("#GPS").click(function () {
function Location() { };
Location.prototype.getLocation = function (callback) {
var options = {
enableHighAccuracy: true,
maximumAge: 1000
};
this.callback = Object.prototype.toString.call(callback) == "[object Function]" ?
callback :
function (address) {
alert(address.province + address.city);
console.log("getocation(callbackFunction) 可获得定位信息对象");
};
var self = this;
if (navigator.geolocation) {
//浏览器⽀持geolocation
navigator.geolocation.getCurrentPosition(function (position) {
//经度
var longitude = position.coords.longitude;
//纬度
var latitude = position.coords.latitude;
self.loadMapApi(longitude, latitude);
console.log("经度:" + longitude + ",纬度:" + latitude);
var cons= GpsToGcj02(longitude, latitude);
console.log(cons);
var lng_lat_2 = gcj02tobd09(cons[0], cons[1]);
console.log('百度坐标...', lng_lat_2);
///ajax请求高德定位api,返回具体位置
let AppKey = "你刚才申请的AppKey";
let lat = cons[0], lng = cons[1], coordsys = "baidu";//经纬度,以及坐标系类型,此处用的是wgs84转的百度坐标系,
$.ajax({
url: '@Url.Action("GetLocation")',
type: 'post',
data: { lat:lat,lng:lng,AppKey:AppKey,coordsys:coordsys },
success: function (result) {
if (result.status == "1")
{
console.log(result);
}
}
})
}, self.onError, options);
} else {
//浏览器不⽀持geolocation
alert("浏览器不⽀持定位");
}
};
Location.prototype.loadMapApi = function (longitude, latitude) {
var self = this;
var oHead = document.getElementsByTagName('HEAD').item(0);
var oScript = document.createElement("script");
oScript.type = "text/javascript";
oScript.src = "http://api.map.baidu.com/getscript?v=2.0&ak=A396783ee700cfdb9ba1df281ce36862&services=&t=20140930184510";
oHead.appendChild(oScript);
oScript.onload = function (date) {
var point = new BMap.Point(longitude, latitude);
var gc = new BMap.Geocoder();
gc.getLocation(point, function (rs) {
var addComp = rs.addressComponents;
self.callback(addComp);
});
}
};
Location.prototype.onError = function (error) {
switch (error.code) {
case 1:
alert("位置服务被拒绝");
break;
case 2:
alert("暂时获取不到位置信息");
break;
case 3:
alert("获取信息超时");
break;
case 4:
alert("未知错误");
break;
}
};
///WGS-84转火星坐标系GCJ02
function GpsToGcj02(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat]
}
else {
var dlat = transformlat(lng - 105.0, lat - 35.0);
var dlng = transformlng(lng - 105.0, lat - 35.0);
var radlat = lat / 180.0 * PI;
var magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
var mglat = lat + dlat;
var mglng = lng + dlng;
return [mglng, mglat]
}
}
function out_of_china(lng, lat) {
return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
}
function transformlat(lng, lat) {
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
function transformlng(lng, lat) {
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
//火星定位法GCJ-02转百度BD-09坐标系
function gcj02tobd09(lng, lat) {
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return [bd_lng, bd_lat]
}
</script>
前端获取到浏览器的定位以后,可以通过网址发送一些get请求,看看定位效果:
请求地址:https://restapi.amap.com/v3/assistant/coordinate/convert?parameters
AppKey是你自己申请的那个,
然后经纬度是前端发送到后台的经纬度。这里请求的时候用逗号分隔一下,经度在前。
后面的coordsys是经纬度类型。我是转成了百度定位去请求的高德地图的接口,所以填的baidu,
有好几个类型可以填的,具体的参考高德API开发者文档,地址:https://lbs.amap.com/api/webservice/guide/api/convert
C#后端代码:
#region 获取用户定位的相关接口,前端传百度坐标系,后端转高德后继续前端请求,获取具体定位,web手机端需使用Google Chrome 浏览器
public IActionResult GPSIndex()
{
return View();
}
/// <summary>
/// 定位请求,返回高德坐标系
/// </summary>
/// <param name="lat">经度</param>
/// <param name="lng">纬度</param>
/// <param name="AppKey">密钥</param>
/// <param name="coordsys">坐标系类型,此处用百度坐标系</param>
/// <returns></returns>
public IActionResult GetLocation(string lat,string lng,string AppKey, string coordsys)
{
var latlng = string.Format(lat + "," + lng);
//获取高德定位
var location = LocationResult(latlng,AppKey,coordsys);
//获取具体位置
var Gps = GetLocationByLngLat(latlng, AppKey, 10000);
return Json(Gps);
}
/// <summary>
/// 根据经纬度获取地址
/// </summary>
/// <param name="lngLatStr">经度纬度组成的字符串 例如:"113.692100,34.752853"</param>
/// <param name="timeout">超时时间默认10秒</param>
/// <returns>失败返回"" </returns>
public static string GetLocationByLngLat(string lngLatStr,string Key,int timeout = 10000)
{
var url = $"http://restapi.amap.com/v3/geocode/regeo?key={Key}&location={lngLatStr}";
return GetLocationByUrl(url, timeout);
}
/// <summary>
/// 根据经纬度获取地址
/// </summary>
/// <param name="lng">经度 例如:113.692100</param>
/// <param name="lat">维度 例如:34.752853</param>
/// <param name="timeout">超时时间默认10秒</param>
/// <returns>失败返回"" </returns>
public static string GetLocationByLngLat(double lng, double lat,string Key, int timeout = 10000)
{
var url = $"http://restapi.amap.com/v3/geocode/regeo?key={Key}&location={lng},{lat}";
return GetLocationByUrl(url, timeout);
}
/// <summary>
/// 根据URL获取地址
/// </summary>
/// <param name="url">Get方法的URL</param>
/// <param name="timeout">超时时间默认10秒</param>
/// <returns></returns>
private static string GetLocationByUrl(string url, int timeout = 10000)
{
var s = "";
try
{
if (WebRequest.Create(url) is HttpWebRequest req)
{
req.ContentType = "multipart/form-data";
req.Accept = "*/*";
req.UserAgent = "";
req.Timeout = timeout;
req.Method = "GET";
req.KeepAlive = true;
if (req.GetResponse() is HttpWebResponse response)
using (var sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
s = sr.ReadToEnd();
return s;
}
}
}
catch (Exception ex)
{
s = ex.ToString();
}
return s;
}
public static GaodeGetCoding LocationResult(string latlng, string AppKey, string coordsys)
{
var url = "https://restapi.amap.com/v3/assistant/coordinate/convert?parameters";
url += string.Format(AppKey, latlng, coordsys);
var Json = GetResponseString(CreateGetHttpResponse(url, null));
var model = JsonConvert.DeserializeObject<GaodeGetCoding>(Json);
return model;
}
/// <summary>
/// 创建GET方式的HTTP请求
/// </summary>
public static HttpWebResponse CreateGetHttpResponse(string url, CookieCollection cookies)
{
HttpWebRequest request = null;
request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.Proxy = null;
if (cookies != null)
{
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
}
return request.GetResponse() as HttpWebResponse;
}
/// <summary>
/// 获取请求的数据
/// </summary>
public static string GetResponseString(HttpWebResponse webresponse)
{
using (Stream s = webresponse.GetResponseStream())
{
StreamReader reader = new StreamReader(s, Encoding.UTF8);
return reader.ReadToEnd();
}
}
#endregion
返回值的封装:
namespace Rongbo.DDPG.Entity.GaoDeLocationAPI
{
public class GaodeGetCoding
{
/// <summary>
/// 返回状态,1=成功,0=失败
/// </summary>
public int Status { get; set; }
/// <summary>
/// 成功编码 OK
/// </summary>
public string Info { get; set; }
public string InfoCode { get; set; }
public List<Gaode> Regeocode { get; set; }
}
public class Gaode
{
public string Formatted_address { get; set; }
public List<GaodeList> AddressComponent { get; set; }
}
public class GaodeList
{
/// <summary>
/// 国籍
/// </summary>
public string Country { get; set; }
/// <summary>
/// 省名
/// </summary>
public string Province { get; set; }
/// <summary>
/// 市名
/// </summary>
public string City { get; set; }
/// <summary>
/// 市区码
/// </summary>
public string CityCode { get; set; }
/// <summary>
/// 省县名
/// </summary>
public string district { get; set; }
/// <summary>
/// 省县码
/// </summary>
public string adCode { get; set; }
/// <summary>
/// 街道名
/// </summary>
public string TownShip { get; set; }
public string TownCode { get; set; }
public List<StreetNumber> StreetNumber { get; set; }
public List<string> BusinessAreas { get; set; }
public List<Building> Building { get; set; }
public List<Neighborhood> Neighborhood { get; set; }
}
public class Neighborhood
{
public string Name { get; set; }
public string Type { get; set; }
}
public class Building
{
public string Name { get; set; }
public string Type { get; set; }
}
public class StreetNumber
{
public List<string> Street { get; set; }
public List<string> Number { get; set; }
public string Location { get; set; }
public List<string> Direction { get; set; }
public List<string> Distance { get; set; }
}
}
前端返回的Json效果【具体地址是我自己隐藏的】:
{“status”:“1”,“regeocode”:{“addressComponent”:{“city”:“杭州市”,“province”:“浙江省”,“adcode”:“330110”,“district”:“余杭区”,“towncode”:“330110012000”,“streetNumber”:{“number”:“359号”,“location”:“119.993782,30.277486”,“direction”:“西北”,“distance”:“41.1047”,“street”:“舒心路”},“country”:“中国”,“township”:“仓前街道”,“businessAreas”:[[]],“building”:{“name”:[],“type”:[]},“neighborhood”:{“name”:[],“type”:[]},“citycode”:“0571”},“formatted_address”:“浙江省杭州市余杭区仓前街道**********”},“info”:“OK”,“infocode”:“10000”}
然后拿到了以后,你们就可以进行一系列操作了。
方法二:JS获取定位
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: 'dd884f10c2a941075f6f8dc815229528',
}
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=你申请的AppKey"></script>
<script type="text/javascript">
//基本地图加载
var map = new AMap.Map('container', {
resizeEnable: true
});
AMap.plugin('AMap.Geolocation', function () {
var geolocation = new AMap.Geolocation({
enableHighAccuracy: true,//是否使用高精度定位,默认:true
timeout: 5000, //超过10秒后停止定位,默认:5s
position: 'RB', //定位按钮的停靠位置
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
});
map.addControl(geolocation);
//result中包含浏览器ip地址等信息
geolocation.getCurrentPosition(function (status, result) {
if (status == 'complete') {
onComplete(result);
} else {
onError(result)
}
});
});
this.map.plugin('AMap.Geolocation', function () {
geolocation = new AMap.Geolocation({
enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:无穷大
maximumAge: 0, //定位结果缓存0毫秒,默认:0
showButton: true, //显示定位按钮,默认:true
buttonPosition: 'LB', //定位按钮停靠位置,默认:'LB',左下角
buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
showMarker: true, //定位成功后在定位到的位置显示点标记,默认:true
panToLocation: true, //定位成功后将定位到的位置作为地图中心点,默认:true
zoomToAccuracy: true, //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
});
_this.map.addControl(geolocation);
geolocation.getCurrentPosition();
AMap.event.addListener(geolocation, 'complete', function (data) {
var gpsPoint = GPS.gcj_encrypt(data.position.getLat(), data.position.getLng());
_this.centerPointer = gpsPoint;
_this.circleArea(gpsPoint);
_this.getAddress(gpsPoint);
});
AMap.event.addListener(geolocation, 'error', function () {
alert('定位失败');
});
});
var GPS = {
PI: 3.14159265358979324,
x_pi: 3.14159265358979324 * 3000.0 / 180.0,
delta: function (lat, lon) {
var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
var dLat = this.transformLat(lon - 105.0, lat - 35.0);
var dLon = this.transformLon(lon - 105.0, lat - 35.0);
var radLat = lat / 180.0 * this.PI;
var magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
return {
'lat': dLat,
'lon': dLon
};
},
//WGS-84 to GCJ-02
gcj_encrypt: function (wgsLat, wgsLon) {
if (this.outOfChina(wgsLat, wgsLon))
return {
'lat': wgsLat,
'lon': wgsLon
};
var d = this.delta(wgsLat, wgsLon);
return {
'lat': wgsLat + d.lat,
'lon': wgsLon + d.lon
};
},
outOfChina: function (lat, lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
},
transformLat: function (x, y) {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
},
transformLon: function (x, y) {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
};
</script>
以上是JS API的获取方式。
原创不易,看完记得点赞收藏鼓励,你的支持是我最大的原创动力!