方法介绍:
1. 该方法是个 promise 对象,因为不管是用 GPS 还是高德定位都是异步的
2. 方法优先是用 h5 自带 API 进行 GPS 定位,如果获取不到位置会使用高德定位(高德定位需要高德的key)
3. 该 promise 封装的很拙略,能力至此,会慢慢优化的,本来使用的正常方法加回调函数处理获取到的经纬度,但考虑再三还是使用 promise 能好点
注意:
1. 现在很多浏览器需要加密协议的链接才能获取到用户位置,保险起见,请使用加密协议的链接
2. 使用高德定位需要在高德那里申请key
3. 如果需要精度高或者后续还要使用高德地图对经纬度做其他处理,需要将 gps 获取到的经纬度转成高德经纬度,项目头部引得 GPS2AMAP就是处理这个的,代码在下面
1 /* 2 该方法暴露出去的是一个promise,经纬度在resolve的第一个参数里 3 使用方法: startLocation.then(({lat, lng}) => {这里就是你的方法}) 4 */ 5 6 // 将gps 经纬度转为高德经纬度,精度要求高的需要这个东西 7 import { 8 GPS 9 } from './GPS2AMAP' 10 let callback = null // promise 的 resolve会赋值给这个函数 11 // gps 定位成功回调 12 const onSuccess = (position) => { 13 const { 14 latitude: lat, 15 longitude: lng 16 } = position.coords 17 const exchange = GPS.gcj_encrypt(Number.parseFloat(lat), Number.parseFloat(lng)) 18 console.log('gps定位', `${exchange.lat}-${exchange.lng}`) 19 saveLocation(exchange.lat, exchange.lng) 20 } 21 // gps 定位失败回调 22 const onError = () => { 23 initAMAP() 24 console.error('gps失败') 25 } 26 // 初始化高德,加载高德js 27 const initAMAP = () => { 28 const key = 'xxxxxxxxxxx', // 从高德买来的key 29 MP = new Promise(function (resolve, reject) { 30 window.init = function () { 31 resolve(AMap) 32 }; 33 let script = document.createElement("script"); 34 script.type = "text/javascript"; 35 script.src = "//webapi.amap.com/maps?v=1.4.6&key="+key+"&callback=init"; 36 script.onerror = reject; 37 document.head.appendChild(script); 38 }) 39 MP.then(function (AMap) { 40 startAMAPLocation(AMap) 41 }).catch(err=>{ 42 console.error(JSON.stringify(err)); 43 }) 44 } 45 46 // 开始高德定位 47 const startAMAPLocation = (AMap) => { 48 AMap.plugin('AMap.Geolocation', function () { 49 var geolocation = new AMap.Geolocation({ 50 enableHighAccuracy: true, //是否使用高精度定位,默认:true 51 timeout: 8000, //超过10秒后停止定位,默认:5s 52 buttonPosition: 'RB', //定位按钮的停靠位置 53 buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20) 54 zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点 55 }); 56 // map.addControl(geolocation); 57 geolocation.getCurrentPosition(function (status, result) { 58 if (status == 'complete') { 59 console.log('高德: ', `${result.position.lat},${result.position.lng}`) 60 saveLocation(result.position.lat, result.position.lng) 61 } else { 62 console.error('高德失败') 63 saveLocation(0, 0) 64 } 65 }); 66 }); 67 } 68 // 处理获取到的经纬度 69 const saveLocation = (lat = 0, lng = 0) => { 70 lat && (lat = parseFloat(lat).toFixed(6)) 71 lng && (lng = parseFloat(lng).toFixed(6)) 72 typeof callback === 'function' && callback({lat, lng}) 73 } 74 75 // promise, resolve的第一个参数就是经纬度, 76 const startLocation = new Promise((resolve, reject) => { 77 callback = resolve 78 const options = { 79 enableHighAccuracy: true, 80 maximumAge: 1000, 81 timeout: 5000 82 } 83 if (navigator.geolocation) { 84 navigator.geolocation.getCurrentPosition(onSuccess, onError, options) 85 } else { 86 saveLocation(0, 0) 87 console.error('您的浏览器不支持地理位置定位') 88 } 89 }) 90 export default startLocation
这里 GPS2AMAP.js
1 export const GPS = { 2 PI : 3.14159265358979324, 3 x_pi : 3.14159265358979324 * 3000.0 / 180.0, 4 delta : function (lat, lng) { 5 var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 6 var ee = 0.00669342162296594323; // ee: 椭球的偏心率。 7 var dLat = this.transformLat(lng - 105.0, lat - 35.0); 8 var dlng = this.transformlng(lng - 105.0, lat - 35.0); 9 var radLat = lat / 180.0 * this.PI; 10 var magic = Math.sin(radLat); 11 magic = 1 - ee * magic * magic; 12 var sqrtMagic = Math.sqrt(magic); 13 dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI); 14 dlng = (dlng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI); 15 return {'lat': dLat, 'lng': dlng}; 16 }, 17 18 //GPS---高德 19 gcj_encrypt : function ( wgsLat , wgslng ) { 20 if (this.outOfChina(wgsLat, wgslng)) 21 return {'lat': wgsLat, 'lng': wgslng}; 22 23 var d = this.delta(wgsLat, wgslng); 24 return {'lat' : wgsLat + d.lat,'lng' : wgslng + d.lng}; 25 }, 26 outOfChina : function (lat, lng) { 27 if (lng < 72.004 || lng > 137.8347) 28 return true; 29 if (lat < 0.8293 || lat > 55.8271) 30 return true; 31 return false; 32 }, 33 transformLat : function (x, y) { 34 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)); 35 ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0; 36 ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0; 37 ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0; 38 return ret; 39 }, 40 transformlng : function (x, y) { 41 var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); 42 ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0; 43 ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0; 44 ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0; 45 return ret; 46 } 47 };
以上