记前端项目定位实现过程
- 背景:
一个前端h5项目,需要内嵌到企业微信工作台上使用,项目中有获取定位信息的要求
- 实现过程:
① 第一次:目标实现方式是调用高德,使用高德地图来获取经纬度,使用获得的经纬度来获取地理位置名称,
具体实现过程如下:
window._AMapSecurityConfig = {
securityJsCode: "yourSecretKey",
};
const handleGeoLocation = () => {
AMapLoader.load({
key: 'yourkey', // 你的高德地图API Key
version: '2.0', // API 版本
plugins: ['AMap.Geolocation', 'AMap.Geocoder'], // 加载定位和逆地理编码插件
}).then((AMap) => {
// 初始化定位插件
const geolocation = new AMap.Geolocation({
enableHighAccuracy: false, // 是否使用高精度定位
timeout: 20000, // 超时时间
});
// 获取当前位置
geolocation.getCurrentPosition((status, result) => {
if (status === 'complete') {
console.log('定位成功:', result);
// 获取经纬度
const lng = result.position.lng; // 经度
const lat = result.position.lat; // 纬度
// 初始化逆地理编码插件
const geocoder = new AMap.Geocoder({
city: '全国', // 城市,默认设置为“全国”
radius: 1000, // 逆地理编码搜索半径
});
// 调用逆地理编码接口
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.info === 'OK') {
// 逆地理编码成功
console.log('逆地理编码成功:', result.regeocode.formattedAddress);
} else {
// 逆地理编码失败
console.error('逆地理编码失败:', result);
}
});
} else {
console.error('定位失败:', result);
}
});
}).catch((error) => {
console.error('高德地图 API 加载失败:', error);
});
return;
}
问题说明:
这种情况有一个前提条件是项目的运行浏览器不使用谷歌浏览器,谷歌浏览器是国外的浏览器,由于国内网络保护,导致无法获取当前定位,也就是说,在谷歌浏览器上调用getCurrentPosition方法会报错。具体的原因,帖子上有说把协议改为https就可以调用成功的,本人试了一下,没生效,而且还有一点是,高德地图在localhost也就是本地开发的情况下,是不会做协议限制的,由此也可知,调用不通和协议无关,高德地图官网上也阐述了,谷歌浏览器的定位本身就是一个黑洞,不建议使用。至于具体的原因,目前据我所查没有一个帖子有比较明确的答案(有无大佬评论区解释下,多谢)。这里具体的应该要涉及到各个浏览器定位实现的方式,定位实现的方式各有不同的,具体感兴趣的可以查查。
② 第二次:考虑纯后端实现
获取定位失败的原因未可知,就无法根据问题解决,除了换浏览器,但是企业微信工作台的浏览器是不可能改变的,所以考虑纯后端实现
(说到这里就要进行展开,由于企业微信的内核和谷歌浏览器一样,导致我以为问题出现在企业微信工作台浏览器使用谷歌的缘故,但实质上,企业微信工作台上应用无法调通定位接口的原因是,获得地理位置等信息都属于私人信息,出于安全考虑,内嵌浏览器会禁用所有的敏感信息的获取,所以在没有授权允许的情况下,是无法获得定位的)
纯后端实现是不可能的,后端只能通过解析ip地址来获取的一个大概的信息,地址也就精确到城市,市面上所有的定位都是前端实现的,当然有这种想法也是由于上述的那个说法,都是泪
③ 最后一次:一个正确的实现方案
针对此类型的开发,对于内嵌到企业微信或者钉钉的应用,获取地理信息位置,在对应的开发者工具里面都有具体的实现,这些具体的实现,开发者工具的官网上都有具体的实现,针对企业微信内嵌应用的实现如下:
// 这里的decodeGeocoder使用的是公司封装的解码包,本质上还是用的高德地图的实现 function getDynamicAddress(lng_lat:any = []) { const geolocation = new Geolocation(); try { // 初始化 await geolocation.init(); await geolocation.initGeolocation(); // 解析地址 await geolocation.initGeocoder(); const addressInfo = await geolocation.decodeGeocoder(lng_lat); return { lngLat: lng_lat, address: addressInfo.address, fullInfo: addressInfo.regeocodeInfo, }; } catch (error) { console.error("获取地址失败:", error); throw error; } } async function handleGeolocation() { try { // 1. 获取当前页面URL(去除hash部分) const currentPageUrl = window.location.href.split('#')[0]; console.log('当前页面URL:', currentPageUrl); // 2. 从后端获取配置信息 const res = await request({ url: workOrderService.dispatchOrder.queryGeolocation, method: 'GET', params: { url: currentPageUrl }, }); if (!res?.success || !res?.data) { console.error('获取配置失败:', res); return; } // 3. 检查wx对象是否存在 if (typeof wx === 'undefined') { console.error('企业微信JS-SDK未加载'); return; } // 4. 初始化配置 wx.config({ beta: true, debug: false, // 生产环境建议关闭 appId: res.data.appId, // 使用确定存在的值,避免可选链 timestamp: res.data.timestamp, nonceStr: res.data.nonceStr, signature: res.data.signature, jsApiList: ['getLocation'], }); // 5. 配置错误处理 wx.error((err) => { console.error('JS-SDK配置失败:', err); // 可以在这里显示错误提示给用户 }); // 6. 配置成功后获取位置 wx.ready(async () => { try { wx.getLocation({ type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: async function (res) { let lat = (+res.latitude).toFixed(6); let lng = (+res.longitude).toFixed(6); console.log('res111', res, lat, lng, res.errMsg == "getLocation:ok"); if (res.errMsg === "getLocation:ok") { console.log('获取位置成功:', lat, lng); const result =await getDynamicAddress([+lng, +lat]); return result; } } }); } catch (error) { console.error('获取位置失败:', error); } }); } catch (error) { console.error('处理地理位置出错:', error); } }
浙公网安备 33010602011771号