在学习HeadFirstHtml5中,学到了地理定位,之前用过百度的地图SDK,
是毕业设计Android APP的其中的一个小功能,这次我们用Google开放的API,
使用JS来实现浏览器的地理定位。
定位原理:
一般是GPS定位(4颗卫星,利用电磁波来定位), 或者基站三角定位(利用信号强度定位), 以及WIFI定位(你开了WIFI就能扫描到附近的WIFI,如果此时你开启了定位,就会收集到位置服务器,你附近的WIFI也会收集起来,包括他们的MAC地址,根据信号衰减公式就能推算出它们的距离)。wifi可以进行室内定位,一般情况下室外精度是GPS>WIFI>基站.另外有政策不允许那么准。
参考手册:
https://developers.google.cn/maps/documentation/javascript/tutorial
https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs
第三方API,从某种角度讲,是植根于第三方服务器上的。要通过 JavaScript获取它们,您首先需要链接到其功能接口上并使其在您的页面上生效。通常来说,这首先需要您通过一个 <script> 元素连接到第三方服务器所开放的JavaScript库,
<script src="https://maps.googleapis.com/maps
/api/js?key=AIzaSyDJW4jsPlNKgv6jFm3B5Edp5ywgdqL
Wdmc&sensor=true"></script>
其中第三方API一般来说都需要申请开发者的APIKEY,不过上述的apikey可以直接使用。这样你就可以使用人家库中的对象和方法了。
javascript主要提供的方法有三种:
navigator.geolocation.getCurrentPosition(displayLocation, displayError, options)
navigator.geolocation.watchPosition(displayLocation, displayError, options)
navigator.geolocation.clearWatch(watchId)
我们要做的是利用getCurrentPosition获得我们的位置,第一次会弹出请求框,点击允许就可以。
获取位置之后创建地图,同时创建Marker标记我们的位置,然后控制精度、地图类型等等,获取我们
关心的数据。
下面是代码,可以对照文档阅读:
myLoc.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Wherever you go, there you are</title>
<script src="myLoc.js"></script>
<!-- 这里的sensor=true的参数表示使用地图同时使用我的位置-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDJW4jsPlNKgv6jFm3B5Edp5ywgdqLWdmc&sensor=true"></script>
<link rel="stylesheet" href="myLoc.css">
</head>
<body>
<form>
<input type="button" id="watch" value="Watch me">
<input type="button" id="clearWatch" value="Clear watch">
</form>
<div id="location">
Your location will go here.
</div>
<div id="distance">
Distance from WickedlySmart HQ will go here.
</div>
<div id="map">
</div>
</body>
</html>
myLoc.css
/*
* myLoc.css
*
*/
body {
font-family: Arial, Helvetica, sans-serif;
margin: 10px;
}
form, div#location, div#distance {
padding: 5px;
}
div#map {
margin: 5px;
width: 400px;
height: 400px;
border: 1px solid black;
}
/*
* Use this CSS to make the map full screen
*
html, body, div#map {
width: 100%;
height: 100%;
margin: 0px;
}
form {
position: absolute;
top: 40px;
right: 10px;
z-index: 2;
}
div#location, div#distance {
display: none;
}
*/
myLoc.js
var watchId = null; //可以使用这个id来clearWatch
var prevCoords = null; //我们将前一次定位和最近一次定位的经纬度之间距离计算,大于20米才加入Marker标记
var map; //全局变量map,包含创建的Google地图对象
//这是一个字面量对象
var ourCoords = {
latitude: 47.624851,
longitude: -122.52099
};
window.onload = getMyLocation;
function displayLocation(position) {
//从position.coords对象中获取纬度和经度
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
//获取经纬度
var div = window.document.getElementById("location");
div.innerHTML = "You are at Latitude: " + latitude + ", Longitude: " + longitude;
div.innerHTML += " (with " + position.coords.accuracy + " meters accuracy)";
//计算距离
var km = computeDistance(position.coords, ourCoords);
var distance = document.getElementById("distance");
distance.innerHTML = "You are " + km + " km from the WickedlySmart HQ";
//创建地图 coords对象有latitude、longitude、accuracy、altitude、altitudeAccuracy、heading、
//speed等属性,分别表示纬度、经度、准确度、海拔、海拔经度、你的方向、你的速度
if(map == null){
showMap(position.coords);
prevCoords = position.coords; //记录第一次的坐标对象
} else {
var meters = computeDistance(position.coords, prevCoords) * 1000; //单位转换
if(meters > 20) {
scrollMapToPosition(position.coords);
prevCoords = position.coords;
}
}
}
//计算地理经纬度
//编写 错误处理程序,geolocation对象会向你的处理程序传入一个error对象,
//其中包含一个数值码,描述它未能确定浏览器位置的原因。
function displayError(error) {
alert(typeof(error.code));
var errorTypes = {
0: "Unknown error",
1: "Permission denied by user",
2: "Position is not available",
3: "Request timed out"
};
var errorMessage = errorTypes[error.code];
//这里error.code是一个number值,errorTypes会把数字属性自动转换为字符串,可以直接
//errorTypes[error.code]来索引,也可以用errorTypes["1"]类似形式来索引
if(error.code == 0 || error.code == 2){
//对于0和2错误,error.message可能还有额外的信息
errorMessage = errorMessage + " " + error.message;
}
var div = document.getElementById("location");
div.innerHTML = errorMessage;
}
function getMyLocation() {
if(navigator.geolocation) {
// navigator.geolocation.getCurrentPosition(displayLocation,
// displayError);
var watchButton = document.getElementById("watch");
watchButton.onclick = watchLocation;
var clearWatchButton = document.getElementById("clearWatch");
clearWatchButton.onclick = clearWatch;
} else {
alert("Oops, no geolocation support");
}
}
//利用Haversine公式计算经纬度点之间的距离
function degreesToRadians(degrees) {
var radians = (degrees * Math.PI) / 180;
return radians;
}
function computeDistance(startCoords, destCoords) {
var startLatRads = degreesToRadians(startCoords.latitude);
var startLongRads = degreesToRadians(startCoords.longitude);
var destLatRads = degreesToRadians(destCoords.latitude);
var destLongRads = degreesToRadians(destCoords.longitude);
var Radius = 6371; //radius of the Earth in km
var distance = Math.acos(Math.sin(startLatRads) * Math.sin(destLatRads) +
Math.cos(startLatRads) * Math.cos(destLatRads) *
Math.cos(startLongRads - destLongRads)) * Radius;
return distance;
}
//创建地图 参考开发文档https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs#Adding_a_custom_marker
//google map platform: https://developers.google.cn/maps/documentation/javascript/tutorial
function showMap(coords) {
//使用Google提供的构造函数来创建一个包含经纬度的对象
var googleLatAndLong = new google.maps.LatLng(coords.latitude, coords.longitude);
/**
* Google提供了一些选项来控制如何创建地图。
* zoom: 范围是0~21的一个值,是地图的比例尺
* center: 地图中我们的位置是居中
* mapTypedId: 地图的类型(道路地图、卫星地图、或者二者兼有)
* SATELLITE、HYBRID
*/
var mapOptions = {
zoom: 20,
center: googleLatAndLong,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var mapDiv = document.getElementById("map");
map = new google.maps.Map(mapDiv, mapOptions); //参数是一个元素对象、和我们的选项对象
var title = "Your Location:";
var content = "You are here: " + coords.latitude + ", " + coords.longitude;
addMarker(map, googleLatAndLong, title, content);
}
//创建marker
function addMarker(map, latLong, title, content) {
//makerOptions对象包含了经纬度,地图,标题,以及是否可以点击
var markerOptions = {
position: latLong,
map: map,
title: title,
clickable: true
};
var marker = new google.maps.Marker(markerOptions);
var infoWindowOptions = {
content: content,
position: latLong
};
var infoWindow = new google.maps.InfoWindow(infoWindowOptions);
google.maps.event.addListener(marker, "click", function(){
infoWindow.open(map);
});
// marker.addListener("click", function() {
// infoWindow.open(map, marker);
// })
}
/**
* 持续跟踪位置 geolocation.watchPosition方法有三个参数,
* 成功处理函数,错误处理函数,以及选项控制地理定位的超时时间,最大生存时间,是否最高精度等。
*/
function watchLocation() {
//每次位置更新会调用displayLocation函数
watchId = navigator.geolocation.watchPosition(displayLocation, displayError);
}
function clearWatchButton() {
if(watchId) {
navigator.geolocation.clearWatch(watchId);
watchId = null;
}
}
//移动的时候我们可以在地图上添加多个marker标志,下面定义一个函数
function scrollMapToPosition(coords) {
var latitude = coords.latitude;
var longitude = coords.longtitude;
var latLong = new google.maps.LatLng(latitude, longitude);
map.panTo(latlong); //地图的panTo方法取得坐标对象,移动到地图中心
addMarker(map, latlong, "Your new location", "You moved to: " +
latitude + ", " + longitude);
}
下图是结果:
我们在form表单中创建了两个按钮,分别可以监控我们的实时位置,或者清除我们的位置。
结果如图: 我电脑不容易移动,移动之后只要距离超过20m跨度,就会出现一个红色默认的Marker来标记
当前位置