From 6a6c6b1ac53bebd5d464ecb9a3eb8dc5bf32ea10 Mon Sep 17 00:00:00 2001 From: cwchen <1048842385@qq.com> Date: Wed, 14 Jan 2026 14:53:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=AE=9A=E4=BD=8D=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/static/map.html | 114 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 14 deletions(-) diff --git a/src/static/map.html b/src/static/map.html index acf71c7..a1367fe 100644 --- a/src/static/map.html +++ b/src/static/map.html @@ -412,6 +412,8 @@ }, locationIconCache: null, baiduGeolocation: null, + lastHeading: null, // 记录上一次的方向,用于避免频繁更新图标 + updateMarkerTimer: null, // 防抖定时器 elements: { panel: null, tree: null, @@ -1283,38 +1285,116 @@ }, /** - * 更新定位标记 + * 更新定位标记(使用requestAnimationFrame实现平滑更新,避免闪烁) */ updateLocationMarker() { // 确保地图已加载完成 if (!this.map || !this.state.mapLoaded) { - // 静默返回,不输出警告(地图可能还在加载中) return; } - // 如果没有位置信息,静默返回(定位是异步的,需要时间获取) + // 如果没有位置信息,静默返回 if (!this.state.currentLocation) { - // 不输出警告,因为定位是异步过程,这是正常情况 return; } + // 如果已经有待处理的更新,取消它,重新调度(确保使用最新数据) + if (this.updateMarkerTimer) { + cancelAnimationFrame(this.updateMarkerTimer); + } + + // 使用requestAnimationFrame实现平滑更新,保持实时性 + this.updateMarkerTimer = requestAnimationFrame(() => { + this.updateMarkerTimer = null; + this._doUpdateLocationMarker(); + }); + }, + + /** + * 实际执行更新定位标记(实时更新位置和方向) + */ + _doUpdateLocationMarker() { const { lng, lat } = this.state.currentLocation; - - // 创建百度地图点(已转换为BD09坐标) const point = new BMapGL.Point(lng, lat); - console.log('更新定位标记 - 坐标:', lng, lat, '方向:', this.state.currentHeading); - - // 创建带方向的图标(异步加载图片) - this.createRotatedLocationIcon(this.state.currentHeading).then((icon) => { - // 如果标记已存在,更新位置和图标 - if (this.overlays.locationMarker) { - this.map.removeOverlay(this.overlays.locationMarker); + // 如果标记已存在,直接更新(避免删除重建) + if (this.overlays.locationMarker) { + try { + // 更新位置(百度地图GL API支持setPosition) + if (typeof this.overlays.locationMarker.setPosition === 'function') { + this.overlays.locationMarker.setPosition(point); + } else { + // 如果不支持setPosition,检查位置是否变化 + const currentPoint = this.overlays.locationMarker.getPosition(); + if (!currentPoint || + Math.abs(currentPoint.lng - lng) > 0.00001 || + Math.abs(currentPoint.lat - lat) > 0.00001) { + // 位置变化,需要更新(但尽量不删除重建) + const needsRecreate = true; + if (needsRecreate) { + // 保存当前图标,避免重新创建 + const currentIcon = this.overlays.locationMarker.getIcon(); + this.map.removeOverlay(this.overlays.locationMarker); + this.overlays.locationMarker = new BMapGL.Marker(point, { icon: currentIcon }); + this.map.addOverlay(this.overlays.locationMarker); + } + } + } + + // 实时更新方向(降低阈值到1度,保持实时性) + const headingChanged = !this.lastHeading || Math.abs(this.state.currentHeading - this.lastHeading) >= 1; + + if (headingChanged) { + const oldHeading = this.lastHeading; + this.lastHeading = this.state.currentHeading; + + // 实时更新图标(使用requestAnimationFrame确保平滑) + requestAnimationFrame(() => { + this.createRotatedLocationIcon(this.state.currentHeading).then((icon) => { + if (this.overlays.locationMarker) { + // 优先使用setIcon更新(不删除重建) + if (typeof this.overlays.locationMarker.setIcon === 'function') { + this.overlays.locationMarker.setIcon(icon); + } else { + // 如果不支持setIcon,需要重新创建(但保持位置) + const currentPoint = this.overlays.locationMarker.getPosition() || point; + this.map.removeOverlay(this.overlays.locationMarker); + this.overlays.locationMarker = new BMapGL.Marker(currentPoint, { icon }); + this.map.addOverlay(this.overlays.locationMarker); + } + } + }).catch((error) => { + console.error('更新定位图标失败:', error); + // 恢复旧的方向值 + this.lastHeading = oldHeading; + }); + }); + } + } catch (e) { + // 如果更新失败,重新创建标记 + console.warn('更新标记失败,重新创建:', e); + try { + this.map.removeOverlay(this.overlays.locationMarker); + } catch (e2) { + // 忽略移除错误 + } + this.overlays.locationMarker = null; + this._createNewMarker(point); } + } else { + // 标记不存在,创建新标记 + this._createNewMarker(point); + } + }, - // 创建新标记 + /** + * 创建新的定位标记 + */ + _createNewMarker(point) { + this.createRotatedLocationIcon(this.state.currentHeading).then((icon) => { this.overlays.locationMarker = new BMapGL.Marker(point, { icon }); this.map.addOverlay(this.overlays.locationMarker); + this.lastHeading = this.state.currentHeading; }).catch((error) => { console.error('创建定位图标失败:', error); }); @@ -1546,6 +1626,12 @@ this.state.watchLocationTimer = null; } + // 清理更新标记的定时器 + if (this.updateMarkerTimer !== null) { + cancelAnimationFrame(this.updateMarkerTimer); + this.updateMarkerTimer = null; + } + // 清理百度地图定位实例 if (this.baiduGeolocation) { this.baiduGeolocation = null;