HTML5地理定位
在學習HeadFirstHtml5中,學到了地理定位,之前用過百度的地圖SDK,
是畢業設計Android APP的其中的一個小功能,這次我們用Google開放的API,
使用JS來實現瀏覽器的地理定位。
定位原理:
一般是GPS定位(4顆衛星,利用電磁波來定位), 或者基站三角定位(利用訊號強度定位), 以及WIFI定位(你開了WIFI就能掃描到附近的WIFI,如果此時你開啟了定位,就會收集到位置伺服器,你附近的WIFI也會收集起來,包括他們的MAC地址,根據訊號衰減公式就能推算出它們的距離)。wifi可以進行室內定位,一般情況下室外精度是GPS>WIFI>基站.另外有政策不允許那麼準。
參考手冊:
第三方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來標記
當前位置