前提
这几天在菜鸟学习 HTML5 教程,学到地理定位,发现一个很严重的问题,Google 地理位置服务早已不提供给我国,然,各大教程的代码和方法,都是由 Google 服务支持的,那不就不可用了么?
菜鸟教程:HTML5 Geolocation(地理定位)
我的学习方法是必须照着敲一遍,然后再各大浏览器运行测试一遍,若都可兼容运行那我才会去消化掉这些知识。所以,我把代码放去 Edge(Chrome)、360(IE/Chrome)、Firefox、Safari、Opera 去运行,发现,仅仅只有 Edge 可获取经纬度等数据,其他浏览器各种毛病,要么直接提示不支持或地理信息不可用,要么无反应啥都没出现(由于各种原因 Googel 浏览器在我电脑残留 "卡bug" 无法使用,IE也用360替着测了)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<input type="button" onclick="getLocation()" value="确认" />
<div id="position"></div>
<script type="text/javascript">
var x = document.getElementById('position');
function getLocation() {
// if (navigator.geolocation) {
try {
navigator.geolocation.getCurrentPosition(
function getLocationSuccess(e) {
x.innerHTML = '纬度:' + e.coords.latitude +
'<br/>经度:' + e.coords.longitude;
},
function getLocationError(err) {
switch (err.code) {
case err.PERMISSION_DENIED:
x.innerHTML = '用户拒绝对获取地理位置的请求。<br/>' + err.message;
break;
case err.POSITION_UNAVAILABLE:
x.innerHTML = '位置信息是不可用的。<br/>' + err.message;
break;
case err.TIMEOUT:
x.innerHTML = '请求用户地理位置超时。<br/>' + err.message;
break;
case err.UNKNOWN_ERROR:
x.innerHTML = '未知错误。<br/>' + err.message;
break;
}
}
);
// } else {
} catch (err) {
x.innerHTML = '该浏览器不支持获取地理位置。';
}
}
</script>
</body>
</html>
- Edge(正常运行):
- 360(IE/Chrome)、Firefox、Safari、Opera:
那怎么办,都无法运行,无法使用,那岂不是白学?这么常用的功能跳过也不是办法。所以,我的选择是——使用第三方API(国内)。
百度地图 API (简单教程)
PS:我仿着菜鸟教程分步演示,方便小伙伴们更容易理解和学习。
1. 获取经纬度
-
用到的 API 方法和属性:
- BMap.Geolocation() - 创建百度地图实例对象;
- point.lng - 获取纬度;
- point.lat - 获取经度;
- address.city
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入百度 API,"ak=" 后面一串码是密钥,最好自己申请-->
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=7a6QKaIilZftIMmKGAFLG7QT1GLfIncg"></script>
</head>
<body>
<input type="button" onclick="getLocation()" value="确认" />
<div id="position"></div>
<script type="text/javascript">
var x = document.getElementById('position');
function getLocation() {
// 创建百度地理位置实例,代替 navigator.geolocation
var geolocation = new BMap.Geolocation();
// 其实可不需要判断,API兼容到了IE5
try {
geolocation.getCurrentPosition(function(e) {
// 百度 geolocation 的经纬度属性不同,此处是 point.lat 而不是 coords.latitude
x.innerHTML = '城市:' + e.address.city + '<br/>纬度:' + e.point.lat + '<br/>经度:' + e.point.lng;
});
} catch (err) {
x.innerHTML = '该浏览器不支持获取地理位置。';
console.log(err);
}
}
</script>
</body>
</html>
2. 处理错误和拒绝
常量 | 描述 | 返回值 |
---|---|---|
BMAP_STATUS_SUCCESS | 检索成功 | 对应数值 "0" |
BMAP_STATUS_CITY_LIST | 城市列表 | 对应数值 "1" |
BMAP_STATUS_UNKNOWN_LOCATION | 位置结果未知 | 对应数值 "2" |
BMAP_STATUS_UNKNOWN_ROUTE | 导航结果未知 | 对应数值 "3" |
BMAP_STATUS_INVALID_KEY | 非法密钥 | 对应数值 "4" |
BMAP_STATUS_INVALID_REQUEST | 非法请求 | 对应数值 "5" |
BMAP_STATUS_PERMISSION_DENIED | 没有权限 | 对应数值 "6" (自 1.1 新增) |
BMAP_STATUS_SERVICE_UNAVAILABLE | 服务不可用 | 对应数值 "7" (自 1.1 新增) |
BMAP_STATUS_TIMEOUT | 超时 | 对应数值 "8" (自 1.1 新增) |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入百度 API,"ak=" 后面一串码是密钥,最好自己申请-->
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=7a6QKaIilZftIMmKGAFLG7QT1GLfIncg"></script>
</head>
<body>
<input type="button" onclick="getLocation()" value="确认" />
<div id="position"></div>
<script type="text/javascript">
var x = document.getElementById('position');
function getLocation() {
// 创建百度地理位置实例,代替 navigator.geolocation
var geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(function(e) {
// 检测用户是否拒绝授权
if(e.accuracy != null){
switch (this.getStatus()) {
// 检索成功。BMAP_STATUS_SUCCESS
case 0:
// 百度 geolocation 的经纬度属性不同,此处是 point.lat 而不是 coords.latitude
x.innerHTML = '城市:' + e.address.city + '<br/>纬度:' + e.point.lat + '<br/>经度:' + e.point.lng;
break;
// 位置结果未知。BMAP_STATUS_UNKNOWN_LOCATION
case 2:
x.innerHTML = '位置结果未知。';
break;
// 导航结果未知。BMAP_STATUS_UNKNOWN_ROUTE
case 3:
x.innerHTML = '导航结果未知。';
break;
// 非法密钥。BMAP_STATUS_INVALID_KEY
case 4:
x.innerHTML = '非法密钥。';
break;
// 非法请求。BMAP_STATUS_INVALID_REQUEST
case 5:
x.innerHTML = '非法请求。';
break;
// 没有权限。BMAP_STATUS_PERMISSION_DENIED
case 6:
x.innerHTML = '没有权限。';
break;
// 服务不可用。BMAP_STATUS_SERVICE_UNAVAILABLE
case 7:
x.innerHTML = '服务不可用。';
break;
// 超时。BMAP_STATUS_TIMEOUT
case 8:
x.innerHTML = '超时。';
break;
}
} else {
x.innerHTML = '用户拒绝对获取地理位置的请求。';
}
});
}
</script>
</body>
</html>
3. 在地图中显示结果
-
百度地图API功能:
- new BMap.Map("id") - 创建地图实例;
- new BMap.Point(116.331398,39.897445) - 设置地图默认标注"北京";
- centerAndZoom() - 初始化地图;
- map.enableScrollWheelZoom(true) - 允许鼠标滚轮缩放地图;
- map.clearOverlays() - 清除地图上的遮盖物;
- new BMap.Marker() - 创建标注实例;
- map.addOverlay() - 添加遮盖物触发事件;
- map.panTo() - 将中心点改为指定标注;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入百度 API,"ak=" 后面一串码是密钥,最好自己申请-->
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=7a6QKaIilZftIMmKGAFLG7QT1GLfIncg"></script>
</head>
<body>
<input type="button" onclick="getLocation()" value="确认" />
<div id="mapholder" style="height: 300px;width: 300px;"></div>
<div id="position"></div>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("mapholder"); // 注意 id
var point = new BMap.Point(116.331398,39.897445); // 设置地图默认标注"北京"
map.centerAndZoom(point,11);
map.enableScrollWheelZoom(true); // 允许鼠标滚轮缩放地图
var x = document.getElementById('position');
function getLocation() {
// 创建 geolocation 实例,代替 navigator.geolocation
var geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(function(e) {
console.log(e.accuracy);
// 检测用户是否拒绝授权
if(e.accuracy !== null){
switch (this.getStatus()) {
// 检索成功。BMAP_STATUS_SUCCESS
case 0:
// 清除地图上的遮盖物
map.clearOverlays();
// 创建标注实例
var marker = new BMap.Marker(e.point);
// 将标注添加到地图中
map.addOverlay(marker);
map.panTo(e.point);
// 百度 geolocation 的经纬度属性不同,此处是 point.lat 而不是 coords.latitude
x.innerHTML = '城市:' + e.address.city + '<br/>纬度:' + e.point.lat + '<br/>经度:' + e.point.lng;
break;
// 位置结果未知。BMAP_STATUS_UNKNOWN_LOCATION
case 2:
x.innerHTML = '位置结果未知。';
break;
// 导航结果未知。BMAP_STATUS_UNKNOWN_ROUTE
case 3:
x.innerHTML = '导航结果未知。';
break;
// 非法密钥。BMAP_STATUS_INVALID_KEY
case 4:
x.innerHTML = '非法密钥。';
break;
// 非法请求。BMAP_STATUS_INVALID_REQUEST
case 5:
x.innerHTML = '非法请求。';
break;
// 没有权限。BMAP_STATUS_PERMISSION_DENIED
case 6:
x.innerHTML = '没有权限。';
break;
// 服务不可用。BMAP_STATUS_SERVICE_UNAVAILABLE
case 7:
x.innerHTML = '服务不可用。';
break;
// 超时。BMAP_STATUS_TIMEOUT
case 8:
x.innerHTML = '超时。';
break;
}
} else {
x.innerHTML = '用户拒绝对获取地理位置的请求。';
}
});
}
</script>
</body>
</html>
注意!!!!!
有一点需要注意,百度地图API,在 Safari 中无法对用户是否允许请求做除判断!!!(不清楚是兼容BUG还是什么原因)
关于其它浏览器的请求判断,因为找不到官方的方法,所以百度很久才找到这个:
Edge(Chrome)、360(IE/Chrome)、Firefox、Opera
- 请求允许:
- 请求拒绝:
Safari
- 请求允许:
- 请求拒绝:
无奈,我找遍了百度也找不到解决 Safari 问题的办法,除非用自带 Geolocation API,但是这就又回到刚开始我说的,无法获取由 Google 提供的地理信息了。
关于Safari,要么不设置是否授权,直接获取用户地理信息,要么试试其它 API。(可能百度API也有吧,但是我真没找到对用户请求选择进行判断的函数或属性)【Safari】去掉 e.accuracy !== null
,放弃对请求判断
PS:造成的结果是,无论允不允许,都直接返回地理位置。
- 请求允许:
- 请求拒绝: