在学习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来标记

当前位置

html5定位属性 html5定位原理_git