diff --git a/src/static/map.html b/src/static/map.html index 9305379..0ed7ec2 100644 --- a/src/static/map.html +++ b/src/static/map.html @@ -376,7 +376,7 @@ if (xhr.status >= 200 && xhr.status < 300) { const res = Utils.safeParseJSON(encodeURIComponent(xhr.responseText)); resolve(res?.code >= 200 && res?.code < 300 ? (res.data || []) : []); - } else { + } else { resolve([]); } } @@ -418,6 +418,9 @@ headingHistorySize: 5, // 历史记录大小(5个样本的移动平均) lastOrientationUpdateTime: 0, // 上次方向更新时间,用于节流 headingOffset: 0, // 方向偏移量,用于校正方向偏差(度),如果需要反转方向可以设置为180 + lastLocationTime: 0, // 上次位置更新时间 + lastLocationPoint: null, // 上次位置点,用于计算移动速度 + isMoving: false, // 是否在移动状态 elements: { panel: null, tree: null, @@ -717,7 +720,28 @@ } if (shouldUpdate) { - console.log('精确位置更新 - 经度:', point.lng, '纬度:', point.lat, '精度:', accuracy, '米'); + // 检测移动状态(通过位置变化速度) + const now = Date.now(); + if (this.lastLocationTime > 0 && this.lastLocationPoint && this.state.currentLocation) { + const distance = calculateDistance( + this.state.currentLocation.lng, + this.state.currentLocation.lat, + point.lng, + point.lat + ); + const timeDiff = (now - this.lastLocationTime) / 1000; // 秒 + if (timeDiff > 0) { + const speed = distance / timeDiff; // 米/秒 + // 如果速度超过0.3米/秒(约1公里/小时),认为在移动 + this.isMoving = speed > 0.3; + } + } + + this.lastLocationTime = now; + this.lastLocationPoint = { lng: point.lng, lat: point.lat }; + + console.log('精确位置更新 - 经度:', point.lng, '纬度:', point.lat, '精度:', accuracy, '米', + this.isMoving ? '(移动中)' : '(静止)'); this.state.currentLocation = { lng: point.lng, lat: point.lat, @@ -778,9 +802,24 @@ oldLocation.lng, oldLocation.lat, point.lng, point.lat ) : 0; + // 检测移动状态(通过位置变化速度) + const now = Date.now(); + if (this.lastLocationTime > 0 && this.lastLocationPoint) { + const timeDiff = (now - this.lastLocationTime) / 1000; // 秒 + if (timeDiff > 0) { + const speed = distance / timeDiff; // 米/秒 + // 如果速度超过0.3米/秒(约1公里/小时),认为在移动 + this.isMoving = speed > 0.3; + } + } + + this.lastLocationTime = now; + this.lastLocationPoint = { lng: point.lng, lat: point.lat }; + console.log('位置更新 - 经度:', point.lng, '纬度:', point.lat, '精度:', accuracy, '米', - oldLocation ? `移动距离: ${distance.toFixed(2)}米` : ''); + oldLocation ? `移动距离: ${distance.toFixed(2)}米` : '', + this.isMoving ? '(移动中)' : '(静止)'); this.state.currentLocation = { lng: point.lng, @@ -842,7 +881,7 @@ }; console.log('GPS坐标转换完成 - BD09:', bd09.lng, bd09.lat); this.updateLocationMarker(); - } else { + } else { console.error('GPS坐标转换失败,使用GCJ02定位'); this.startUniAppGeolocation(); } @@ -906,7 +945,7 @@ }; console.log('坐标转换完成 - BD09:', bd09.lng, bd09.lat); this.updateLocationMarker(); - } else { + } else { console.error('坐标转换失败,使用备用方案'); // 如果转换失败,尝试使用百度地图定位 if (typeof BMapGL !== 'undefined' && BMapGL.Geolocation) { @@ -1079,8 +1118,8 @@ }; console.log('GCJ02转BD09成功:', result.lng, result.lat); if (callback) callback(result); - return; - } + return; + } } catch (e) { console.error('GCJ02转BD09解析失败:', e); } @@ -1162,9 +1201,9 @@ const fallback = this.wgs84ToBd09Fallback(wgs_lng, wgs_lat); console.warn('使用备用算法:', fallback); if (callback) callback(fallback); - return; - } - + return; + } + // 计算偏移距离(用于调试) const offsetLng = result.lng - wgs_lng; const offsetLat = result.lat - wgs_lat; @@ -1353,7 +1392,9 @@ } // 实时更新方向(使用角度差值计算,考虑0-360度边界) - const headingChanged = !this.lastHeading || Math.abs(this.angleDifference(this.state.currentHeading, this.lastHeading)) >= 1; + // 移动时提高阈值(2度),减少抖动;静止时降低阈值(1度),保持响应性 + const headingThreshold = this.isMoving ? 2 : 1; + const headingChanged = !this.lastHeading || Math.abs(this.angleDifference(this.state.currentHeading, this.lastHeading)) >= headingThreshold; if (headingChanged) { const oldHeading = this.lastHeading; @@ -1558,14 +1599,22 @@ /** * 移动平均滤波(减少抖动) + * 移动时使用更强的平滑,静止时使用较弱的平滑 */ smoothHeading(rawHeading) { // 初始化历史记录数组和大小(如果不存在) if (!this.headingHistory) { this.headingHistory = []; } + + // 根据移动状态动态调整历史记录大小 + // 移动时使用更多样本(10个)进行更强的平滑,静止时使用较少样本(5个)保持响应性 + const targetHistorySize = this.isMoving ? 10 : 5; if (!this.headingHistorySize) { - this.headingHistorySize = 5; // 默认5个样本的移动平均 + this.headingHistorySize = targetHistorySize; + } else { + // 动态调整历史记录大小 + this.headingHistorySize = targetHistorySize; } // 添加到历史记录 @@ -1575,7 +1624,8 @@ } // 如果历史记录不足,直接返回原始值 - if (this.headingHistory.length < 3) { + const minHistorySize = this.isMoving ? 5 : 3; // 移动时需要更多样本 + if (this.headingHistory.length < minHistorySize) { return rawHeading; } @@ -1644,7 +1694,7 @@ if (response === 'granted') { console.log('设备方向权限已授予,监听旋转矢量传感器'); window.addEventListener('deviceorientation', this.handleOrientation, { passive: false }); - } else { + } else { console.warn('设备方向权限被拒绝,尝试传统传感器'); this.fallbackToTraditionalSensor(); } @@ -1738,8 +1788,13 @@ const oldHeading = this.state.currentHeading; const diff = Math.abs(this.angleDifference(newHeading, oldHeading)); - if (diff >= 1 || oldHeading === 0) { + // 移动时提高阈值(2度),减少抖动;静止时降低阈值(1度),保持响应性 + const threshold = this.isMoving ? 2 : 1; + + if (diff >= threshold || oldHeading === 0) { this.state.currentHeading = newHeading; + console.log('方向更新:', newHeading.toFixed(1), '度', '变化:', diff.toFixed(1), '度', this.isMoving ? '(移动中)' : '(静止)'); + if (this.state.currentLocation) { requestAnimationFrame(() => { this.updateLocationMarker(); @@ -1911,6 +1966,10 @@ if (this.headingHistory) { this.headingHistory = []; } + // 重置移动状态相关变量 + this.isMoving = false; + this.lastLocationTime = 0; + this.lastLocationPoint = null; this.lastOrientationUpdateTime = 0; // 移除定位标记 @@ -1959,7 +2018,7 @@ this.elements.projectListContainer.innerHTML = '
暂无工程数据
'; return; } - + const fragment = document.createDocumentFragment(); projectInfo.forEach((project, index) => { const projectId = project.id || `project-${index}`; @@ -2242,13 +2301,13 @@ }, renderTreeNode(node, container, level) { - const nodeDiv = document.createElement('div'); - nodeDiv.className = 'tree-node'; + const nodeDiv = document.createElement('div'); + nodeDiv.className = 'tree-node'; nodeDiv.style.paddingLeft = (level * 20) + 'px'; - - const itemDiv = document.createElement('div'); - itemDiv.className = 'tree-node-item'; - + + const itemDiv = document.createElement('div'); + itemDiv.className = 'tree-node-item'; + const hasChildren = node.children && node.children.length > 0; // 展开图标 @@ -2275,21 +2334,21 @@ } // 复选框 - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.className = 'tree-node-checkbox'; + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.className = 'tree-node-checkbox'; checkbox.dataset.id = node.id; // 添加data-id用于全选/全不选时更新UI checkbox.checked = this.state.checkedNodeIds.includes(node.id); checkbox.addEventListener('change', (e) => this.handleCheck(node, e.target.checked)); itemDiv.appendChild(checkbox); - + // 文本 - const label = document.createElement('span'); - label.className = 'tree-node-label'; + const label = document.createElement('span'); + label.className = 'tree-node-label'; label.textContent = node.nodeName || node.name || `Node ${node.id}`; - itemDiv.appendChild(label); + itemDiv.appendChild(label); - nodeDiv.appendChild(itemDiv); + nodeDiv.appendChild(itemDiv); // 子容器 if (hasChildren) {