图标定位修改

This commit is contained in:
cwchen 2026-01-14 16:49:02 +08:00
parent 8e34a4a5a7
commit aeed25cb3f
1 changed files with 74 additions and 16 deletions

View File

@ -421,6 +421,7 @@
lastLocationTime: 0, // 上次位置更新时间 lastLocationTime: 0, // 上次位置更新时间
lastLocationPoint: null, // 上次位置点,用于计算移动速度 lastLocationPoint: null, // 上次位置点,用于计算移动速度
isMoving: false, // 是否在移动状态 isMoving: false, // 是否在移动状态
screenOrientation: 'landscape', // 屏幕方向:'landscape'(横屏)或 'portrait'(竖屏)
elements: { elements: {
panel: null, panel: null,
tree: null, tree: null,
@ -1549,18 +1550,24 @@
// 转换公式:画布角度 = 90度 - 地图角度因为画布的0度对应地图的90度 // 转换公式:画布角度 = 90度 - 地图角度因为画布的0度对应地图的90度
// 应用方向偏移量(用于校正方向偏差) // 应用方向偏移量(用于校正方向偏差)
const adjustedHeading = this.normalizeHeading(heading + (this.headingOffset || 0)); let adjustedHeading = this.normalizeHeading(heading + (this.headingOffset || 0));
// 根据屏幕方向进一步调整(如果需要)
// 注意方向校正已经在handleOrientation中处理这里通常不需要再次调整
// 但如果图标旋转仍有问题,可以在这里添加额外的校正
// 转换为画布旋转角度 // 转换为画布旋转角度
// 标准转换画布的0度向右对应地图的90度正东 // 标准转换画布的0度向右对应地图的90度正东
// 所以:画布角度 = 90度 - 地图角度 // 所以:画布角度 = 90度 - 地图角度
// 根据屏幕方向调整旋转角度
let rotation = (90 - adjustedHeading) * Math.PI / 180; let rotation = (90 - adjustedHeading) * Math.PI / 180;
// 如果方向仍然不对,可以尝试以下方案(取消注释): // 如果横屏和竖屏方向表现不同,可以在这里进一步调整
// 方案1反转180度 // 例如竖屏时可能需要额外的180度反转
// rotation = (270 - adjustedHeading) * Math.PI / 180; // if (this.screenOrientation === 'portrait') {
// 方案2直接使用heading如果图标本身已经指向正确方向 // rotation = (270 - adjustedHeading) * Math.PI / 180;
// rotation = -adjustedHeading * Math.PI / 180; // }
ctx.rotate(rotation); ctx.rotate(rotation);
@ -1587,6 +1594,18 @@
return heading; 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度边界 * 计算两个角度之间的最短差值考虑0-360度边界
*/ */
@ -1680,6 +1699,22 @@
this.headingHistory = []; this.headingHistory = [];
this.lastOrientationUpdateTime = 0; this.lastOrientationUpdateTime = 0;
// 检测屏幕方向
this.detectScreenOrientation();
// 监听屏幕方向变化
if (window.addEventListener) {
window.addEventListener('resize', () => {
this.detectScreenOrientation();
});
// 监听orientationchange事件移动设备
window.addEventListener('orientationchange', () => {
setTimeout(() => {
this.detectScreenOrientation();
}, 100); // 延迟100ms确保方向已改变
});
}
console.log('开始监听设备方向(优先使用旋转矢量传感器)...'); console.log('开始监听设备方向(优先使用旋转矢量传感器)...');
// 1. 优先尝试使用旋转矢量传感器通过DeviceOrientationEvent的quaternion // 1. 优先尝试使用旋转矢量传感器通过DeviceOrientationEvent的quaternion
@ -1867,15 +1902,10 @@
else if (event.alpha !== null && event.alpha !== undefined && !isNaN(event.alpha)) { else if (event.alpha !== null && event.alpha !== undefined && !isNaN(event.alpha)) {
// event.alpha 是绕Z轴旋转的角度0-360度 // event.alpha 是绕Z轴旋转的角度0-360度
// 在某些设备上alpha是逆时针的需要转换为顺时针 // 在某些设备上alpha是逆时针的需要转换为顺时针
// 根据设备类型调整Android通常需要反转iOS可能不需要 // 根据实际测试Android设备通常需要反转
// 先尝试不反转 // 尝试反转360 - alpha
rawHeading = event.alpha; rawHeading = (360 - event.alpha) % 360;
console.log('使用传统传感器(alpha):', event.alpha.toFixed(1), '度 ->', rawHeading.toFixed(1), '度');
// 如果方向反了,可以尝试反转(取消下面的注释):
// rawHeading = (360 - event.alpha) % 360;
// 或者使用headingOffset来校正更灵活
// this.headingOffset = 180; // 在初始化时设置
} }
// 4. iOS Safari 使用 webkitCompassHeading // 4. iOS Safari 使用 webkitCompassHeading
else if (event.webkitCompassHeading !== null && event.webkitCompassHeading !== undefined) { else if (event.webkitCompassHeading !== null && event.webkitCompassHeading !== undefined) {
@ -1887,8 +1917,36 @@
} }
if (rawHeading !== null && !isNaN(rawHeading)) { 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); this.updateHeadingIfChanged(smoothedHeading);