news 2026/5/21 14:59:03

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
uniapp的app/h5实现地图连续定位

目录

一、实现逻辑

1、点击定位按钮,调用locatedRender方法

2、app端由于本身自带的定位不太准确,用了原生方法plus.geolocation.watchPosition,并用了高德的key(key需要自己申请),且用了gcoord来转换坐标系

3、由于app端的地图限制,以下涉及地图的方法是写在视图层的,即在里面,而不是在逻辑层里面

二、引用的方法

1、在地图上创建点标记(createMarker)

2、缩放到地图中间(zoomMapToPoint)或者地图上半部分(zoomMapToPointTop)

3、追踪用户位置

在地图基础框架已经搭好的前提下,即window._map已存在

:app端只测试了安卓系统,不知道ios是否适用

一、实现逻辑

1、点击定位按钮,调用locatedRender方法

2、app端由于本身自带的定位不太准确,用了原生方法plus.geolocation.watchPosition,并用了高德的key(key需要自己申请),且用了gcoord来转换坐标系

连续定位,uniapp官方(https://uniapp.dcloud.net.cn/api/location/location-change.html)也有对应的方法,但是在我本地实测,会出现延迟的情况,就是走了好几米,但是定位还是不动,不实时变化,会在10~30秒后,定位跳一下

3、由于app端的地图限制,以下涉及地图的方法是写在视图层的,即在<script module="maptalksJS" lang="renderjs"></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('浏览器不支持地理位置。'); } };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 14:59:01

Win11Debloat:让Windows 11重获新生,一键告别系统臃肿

Win11Debloat&#xff1a;让Windows 11重获新生&#xff0c;一键告别系统臃肿 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declu…

作者头像 李华
网站建设 2026/5/21 14:58:26

OOTDiffusion虚拟试衣:基于扩散模型的服装融合技术深度解析

OOTDiffusion虚拟试衣&#xff1a;基于扩散模型的服装融合技术深度解析 【免费下载链接】OOTDiffusion [AAAI 2025] Official implementation of "OOTDiffusion: Outfitting Fusion based Latent Diffusion for Controllable Virtual Try-on" 项目地址: https://gi…

作者头像 李华
网站建设 2026/5/21 14:57:54

5分钟掌握Pulover‘s Macro Creator:零代码实现智能自动化革命

5分钟掌握Pulovers Macro Creator&#xff1a;零代码实现智能自动化革命 【免费下载链接】PuloversMacroCreator Automation Utility - Recorder & Script Generator 项目地址: https://gitcode.com/gh_mirrors/pu/PuloversMacroCreator 你是否每天花费数小时在重复…

作者头像 李华
网站建设 2026/5/21 14:55:33

培养强大内心心态,教会孩子直面挫折与压力

很多家长心疼孩子&#xff0c;总想替他扫清一切障碍。但真正的强大&#xff0c;不是从不跌倒&#xff0c;而是跌倒了能自己站起来。培养孩子内心的韧性&#xff0c;不需要刻意制造困难&#xff0c;而是在日常小事中换一种回应方式。当孩子积木搭不好、比赛输了、和同学闹矛盾时…

作者头像 李华
网站建设 2026/5/21 14:55:02

机器标识重置技术:如何优雅地绕过Cursor的试用限制

机器标识重置技术&#xff1a;如何优雅地绕过Cursor的试用限制 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your trial …

作者头像 李华
网站建设 2026/5/21 14:50:36

AntiDupl.NET:智能图片去重工具的完整使用指南与实战方案

AntiDupl.NET&#xff1a;智能图片去重工具的完整使用指南与实战方案 【免费下载链接】AntiDupl A program to search similar and defect pictures on the disk 项目地址: https://gitcode.com/gh_mirrors/an/AntiDupl 在数字时代&#xff0c;我们每天都在积累大量的图…

作者头像 李华