uniapp的app/h5实现地图连续定位

发布时间:2026/5/21 14:59:16

uniapp的app/h5实现地图连续定位 目录一、实现逻辑1、点击定位按钮调用locatedRender方法2、app端由于本身自带的定位不太准确用了原生方法plus.geolocation.watchPosition并用了高德的keykey需要自己申请且用了gcoord来转换坐标系3、由于app端的地图限制以下涉及地图的方法是写在视图层的即在里面而不是在逻辑层里面二、引用的方法1、在地图上创建点标记createMarker2、缩放到地图中间zoomMapToPoint或者地图上半部分zoomMapToPointTop3、追踪用户位置在地图基础框架已经搭好的前提下即window._map已存在注app端只测试了安卓系统不知道ios是否适用一、实现逻辑1、点击定位按钮调用locatedRender方法2、app端由于本身自带的定位不太准确用了原生方法plus.geolocation.watchPosition并用了高德的keykey需要自己申请且用了gcoord来转换坐标系连续定位uniapp官方https://uniapp.dcloud.net.cn/api/location/location-change.html也有对应的方法但是在我本地实测会出现延迟的情况就是走了好几米但是定位还是不动不实时变化会在10~30秒后定位跳一下3、由于app端的地图限制以下涉及地图的方法是写在视图层的即在script modulemaptalksJS langrenderjs/script里面而不是在逻辑层script/script里面我这儿主要是为了做app端只是作了h5的兼容如果只是h5正常在script/script里面写就行import gcoord from gcoord; point: [], watchId: null, locationlayer: null, dwOpen:false, this.locationlayer new maptalks.VectorLayer(locationLayer).addTo(window._map);/** * 定位用户当前位置 */ locatedRender() { if (this.point.length 0) { // 放大到当前用户位置地图上半部分 // zoomMapToPointTop(window._map, this.point); // 放大到当前用户位置居中位置 zoomMapToPoint(window._map, this.point); // 在地图上创建标记 createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false); } else { // 启动位置追踪 this.startTrackingWz(); } }, /** * 启动追踪用户位置 */ startTrackingWz() { // #ifdef APP-PLUS this.watchId trackUserLocationApp( position { // 使用 gcoord 转换 → WGS84 const wgs84 gcoord.transform( [position.coords.longitude, position.coords.latitude], // 必须是 [经度, 纬度] gcoord.GCJ02, // 来源坐标系 gcoord.WGS84 // 目标坐标系 ) this.point wgs84 if (this.point this.dwOpen false) { // 设置只有第一次点击的时候才放大缩放 // zoomMapToPointTop(window._map, this.point); zoomMapToPoint(window._map, this.point); this.dwOpen true } createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false); // 在地图上添加标记 }, error { console.error(追踪用户位置出错, error); } ); // #endif // #ifdef H5 this.watchId trackUserLocation( position { this.point [position.coords.longitude, position.coords.latitude]; if (this.point this.dwOpen false) { // 设置只有第一次点击的时候才放大缩放 // zoomMapToPointTop(window._map, this.point); zoomMapToPoint(window._map, this.point); this.dwOpen true } createMarker(window._map, this.locationlayer, this.point[0], this.point[1], false); // 在地图上添加标记 }, error { console.error(追踪用户位置出错, error); } ); // #endif }, /** * 清除位置追踪 */ watchIdClearRender(){ if(this.watchId){ // #ifdef APP-PLUS plus.geolocation.clearWatch(this.watchId); // #endif // #ifdef H5 navigator.geolocation.clearWatch(this.watchId); // #endif } },二、引用的方法1、在地图上创建点标记createMarker/** * 在地图上创建标记 * param {Object} map 地图实例 * param {Object} locationLayer 标注图层 * param {number} lng 经度 * param {number} lat 纬度 * param {boolean} isZoom 是否缩放到该点 */ export const createMarker (map, locationLayer, lng, lat, isZoom false, oldMarker null) { const marker new maptalks.Circle([lng, lat], 0, { symbol: { markerType: ellipse, markerWidth: 10, markerHeight: 10, markerFill: red, markerLineColor: #fff, markerLineWidth: 2, opacity: 1 } }); const markerCenter new maptalks.Marker([lng, lat], { symbol: { markerType: ellipse, markerWidth: 10, markerHeight: 10, markerFill: red, markerLineColor: #fff, markerLineWidth: 2 } }); locationLayer.clear(); locationLayer.addGeometry(marker); locationLayer.addGeometry(markerCenter); if (isZoom) { map.setZoom(18); map.setCenter([lng, lat]); } animateRipple(marker); }; /** * 为标记添加波纹动画效果 * param {Object} marker 标记实例 */ const animateRipple (marker) { const maxMarkerSize 40; const minMarkerSize 10; const duration 1500; let startTime null; function animate(timestamp) { if (!startTime) startTime timestamp; const progress timestamp - startTime; const scaleFactor progress / duration; const currentSize minMarkerSize (maxMarkerSize - minMarkerSize) * scaleFactor; const currentOpacity 1 - scaleFactor; marker.updateSymbol({ markerWidth: currentSize, markerHeight: currentSize, opacity: currentOpacity }); if (progress duration) { startTime timestamp; } requestAnimationFrame(animate); } requestAnimationFrame(animate); };2、缩放到地图中间zoomMapToPoint或者地图上半部分zoomMapToPointTop/** * 缩放地图到指定坐标居中定位 * param {Object} map 地图实例 * param {Array} coordinates 坐标数组 */ export const zoomMapToPoint (map, coordinates) { map.animateTo({ center: coordinates, zoom: 18, pitch: 0, bearing: 0 }, { duration: 1500, easing: out }); }; /** * 缩放地图到指定坐标定位到地图的上半部分 * param {Object} map 地图实例 * param {Array} coordinates 坐标数组 */ export const zoomMapToPointTop (map, coordinates) { map.animateTo({ center: coordinates, zoom: 18, pitch: 0, bearing: 0 }, { duration: 1500, easing: out }); setTimeout(() { //计算需要向上平移的像素距离 例如 向上平移 1/3 地图高度 const mapSize map.getSize(); const dy mapSize.height * -0.3; // 向上平移 1/3 高度 // 平移地图 map.panBy([0, dy], { animation: { duration: 1000 } }); }, 1500); // 等待1500ms若不设置则向上平移不生效 };3、追踪用户位置/** * 追踪用户位置h5 * param {function} successCallback 成功获取位置的回调 * param {function} errorCallback 失败回调 */ export const trackUserLocation (successCallback, errorCallback) { if (navigator.geolocation) { return navigator.geolocation.watchPosition(successCallback, errorCallback, { enableHighAccuracy: true, timeout: 5000, maximumAge: 0 }); } else { console.log(浏览器不支持地理位置。); } }; /** * 追踪用户位置app * param {function} successCallback 成功获取位置的回调 * param {function} errorCallback 失败回调 */ export const trackUserLocationApp (successCallback, errorCallback) { if (plus.geolocation) { return plus.geolocation.watchPosition(successCallback, errorCallback, { provider: amap, // 强制高德关键 type: gcj02, // 高德坐标系 enableHighAccuracy: true, // 高精度 maximumAge: 1000, // 1秒缓存 timeout: 5000 }); } else { console.log(浏览器不支持地理位置。); } };

相关新闻