From aeed25cb3fc04e973ced83fe3877bae050c7060b Mon Sep 17 00:00:00 2001 From: cwchen <1048842385@qq.com> Date: Wed, 14 Jan 2026 16:49:02 +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 | 90 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/src/static/map.html b/src/static/map.html index 0ed7ec2..1a76cef 100644 --- a/src/static/map.html +++ b/src/static/map.html @@ -421,6 +421,7 @@ lastLocationTime: 0, // 上次位置更新时间 lastLocationPoint: null, // 上次位置点,用于计算移动速度 isMoving: false, // 是否在移动状态 + screenOrientation: 'landscape', // 屏幕方向:'landscape'(横屏)或 'portrait'(竖屏) elements: { panel: null, tree: null, @@ -1549,18 +1550,24 @@ // 转换公式:画布角度 = 90度 - 地图角度(因为画布的0度对应地图的90度) // 应用方向偏移量(用于校正方向偏差) - const adjustedHeading = this.normalizeHeading(heading + (this.headingOffset || 0)); + let adjustedHeading = this.normalizeHeading(heading + (this.headingOffset || 0)); + + // 根据屏幕方向进一步调整(如果需要) + // 注意:方向校正已经在handleOrientation中处理,这里通常不需要再次调整 + // 但如果图标旋转仍有问题,可以在这里添加额外的校正 // 转换为画布旋转角度 // 标准转换:画布的0度(向右)对应地图的90度(正东) // 所以:画布角度 = 90度 - 地图角度 + + // 根据屏幕方向调整旋转角度 let rotation = (90 - adjustedHeading) * Math.PI / 180; - // 如果方向仍然不对,可以尝试以下方案(取消注释): - // 方案1:反转180度 - // rotation = (270 - adjustedHeading) * Math.PI / 180; - // 方案2:直接使用heading(如果图标本身已经指向正确方向) - // rotation = -adjustedHeading * Math.PI / 180; + // 如果横屏和竖屏方向表现不同,可以在这里进一步调整 + // 例如:竖屏时可能需要额外的180度反转 + // if (this.screenOrientation === 'portrait') { + // rotation = (270 - adjustedHeading) * Math.PI / 180; + // } ctx.rotate(rotation); @@ -1587,6 +1594,18 @@ return heading; }, + /** + * 检测屏幕方向 + */ + detectScreenOrientation() { + const width = window.innerWidth || window.screen.width; + const height = window.innerHeight || window.screen.height; + // 如果宽度大于高度,认为是横屏;否则是竖屏 + this.screenOrientation = width > height ? 'landscape' : 'portrait'; + console.log('屏幕方向:', this.screenOrientation, `(${width}x${height})`); + return this.screenOrientation; + }, + /** * 计算两个角度之间的最短差值(考虑0-360度边界) */ @@ -1680,6 +1699,22 @@ this.headingHistory = []; this.lastOrientationUpdateTime = 0; + // 检测屏幕方向 + this.detectScreenOrientation(); + + // 监听屏幕方向变化 + if (window.addEventListener) { + window.addEventListener('resize', () => { + this.detectScreenOrientation(); + }); + // 监听orientationchange事件(移动设备) + window.addEventListener('orientationchange', () => { + setTimeout(() => { + this.detectScreenOrientation(); + }, 100); // 延迟100ms确保方向已改变 + }); + } + console.log('开始监听设备方向(优先使用旋转矢量传感器)...'); // 1. 优先尝试使用旋转矢量传感器(通过DeviceOrientationEvent的quaternion) @@ -1867,15 +1902,10 @@ else if (event.alpha !== null && event.alpha !== undefined && !isNaN(event.alpha)) { // event.alpha 是绕Z轴旋转的角度(0-360度) // 在某些设备上,alpha是逆时针的,需要转换为顺时针 - // 根据设备类型调整:Android通常需要反转,iOS可能不需要 - // 先尝试不反转 - rawHeading = event.alpha; - - // 如果方向反了,可以尝试反转(取消下面的注释): - // rawHeading = (360 - event.alpha) % 360; - - // 或者使用headingOffset来校正(更灵活) - // this.headingOffset = 180; // 在初始化时设置 + // 根据实际测试,Android设备通常需要反转 + // 尝试反转:360 - alpha + rawHeading = (360 - event.alpha) % 360; + console.log('使用传统传感器(alpha):', event.alpha.toFixed(1), '度 ->', rawHeading.toFixed(1), '度'); } // 4. iOS Safari 使用 webkitCompassHeading else if (event.webkitCompassHeading !== null && event.webkitCompassHeading !== undefined) { @@ -1887,8 +1917,36 @@ } if (rawHeading !== null && !isNaN(rawHeading)) { + // 根据屏幕方向和移动状态分别校正方向角度 + let correctedHeading = rawHeading; + const isPortrait = this.screenOrientation === 'portrait'; + const isLandscape = this.screenOrientation === 'landscape'; + + // 横屏 + 移动:需要反转180度 + if (this.isMoving && isLandscape) { + correctedHeading = (rawHeading + 180) % 360; + console.log('横屏+移动时方向反转:', rawHeading.toFixed(1), '度 ->', correctedHeading.toFixed(1), '度'); + } + // 横屏 + 静止:保持原始方向或需要特定校正 + else if (!this.isMoving && isLandscape) { + // 横屏静止时,可能需要加180度或保持原样,根据实际测试调整 + // correctedHeading = (rawHeading + 180) % 360; // 如果需要反转,取消注释 + correctedHeading = rawHeading; // 暂时保持原样 + console.log('横屏+静止时方向:', rawHeading.toFixed(1), '度 ->', correctedHeading.toFixed(1), '度'); + } + // 竖屏 + 移动:需要反转180度 + else if (this.isMoving && isPortrait) { + correctedHeading = (rawHeading + 180) % 360; + console.log('竖屏+移动时方向反转:', rawHeading.toFixed(1), '度 ->', correctedHeading.toFixed(1), '度'); + } + // 竖屏 + 静止:需要反转180度 + else if (!this.isMoving && isPortrait) { + correctedHeading = (rawHeading + 180) % 360; + console.log('竖屏+静止时方向反转:', rawHeading.toFixed(1), '度 ->', correctedHeading.toFixed(1), '度'); + } + // 使用移动平均滤波平滑方向数据(减少抖动) - const smoothedHeading = this.smoothHeading(rawHeading); + const smoothedHeading = this.smoothHeading(correctedHeading); // 更新方向(如果变化足够大) this.updateHeadingIfChanged(smoothedHeading);