地图修改

This commit is contained in:
cwchen 2026-01-21 10:53:21 +08:00
parent 0e36e947d0
commit 66c33586d6
2 changed files with 145 additions and 281 deletions

BIN
src/static/image/reset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

View File

@ -32,6 +32,8 @@
padding: 0;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
/* 确保 body 背景色与地图底色一致,防止加载前的白屏 */
background-color: #F5F3F0;
}
#map-container {
@ -386,6 +388,34 @@
transform: scale(0.95);
}
/* 重置地图按钮 */
.reset-map-btn {
position: fixed;
bottom: 70px; /* 定位在定位按钮上方20px + 32px + 18px间距 */
right: 20px;
width: 32px;
height: 32px;
background: rgba(255, 255, 255, 0.95) url('./image/reset.png') center center / 70% no-repeat;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
z-index: 998;
pointer-events: auto;
transition: transform 0.2s, box-shadow 0.2s;
}
.reset-map-btn:hover {
transform: scale(1.1);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}
.reset-map-btn:active {
transform: scale(0.95);
}
/* 地图 Label 样式 - 提取至 CSS */
.map-project-label {
color: #002db6 !important;
@ -466,7 +496,6 @@
<body>
<div id="map-container"></div>
<!-- 工程列表面板 -->
<div id="project-list-panel" class="project-list-panel">
<div class="project-list-container">
<div id="project-list-container"></div>
@ -485,7 +514,7 @@
<div class="model-preview-ar" id="ar-btn">AR</div>
</div>
<!-- 回到定位按钮 -->
<div class="reset-map-btn" id="reset-map-btn" title="重置地图"></div>
<div class="location-center-btn" id="location-center-btn" title="回到当前位置"></div>
</body>
@ -629,24 +658,28 @@
watchPositionId: null,
watchOrientationId: null,
watchLocationTimer: null,
mapLoaded: false
mapLoaded: false,
// 新增:网络状态处理相关
networkDebounceTimer: null,
isNetworkRecovering: false
},
locationIconCache: null,
baiduGeolocation: null,
lastHeading: null, // 记录上一次的方向,用于避免频繁更新图标
updateMarkerTimer: null, // 防抖定时器
headingHistory: [], // 方向历史记录,用于平滑滤波(移动平均)
headingHistorySize: 5, // 历史记录大小5个样本的移动平均
lastOrientationUpdateTime: 0, // 上次方向更新时间,用于节流
headingOffset: 0, // 方向偏移量用于校正方向偏差如果需要反转方向可以设置为180
lastLocationTime: 0, // 上次位置更新时间
lastLocationPoint: null, // 上次位置点,用于计算移动速度
isMoving: false, // 是否在移动状态
lastHeading: null,
updateMarkerTimer: null,
headingHistory: [],
headingHistorySize: 5,
lastOrientationUpdateTime: 0,
headingOffset: 0,
lastLocationTime: 0,
lastLocationPoint: null,
isMoving: false,
elements: {
panel: null,
tree: null,
closeBtn: null,
projectListContainer: null
projectListContainer: null,
resetBtn: null
},
init() {
@ -670,6 +703,9 @@
// 处理 URL Action
this.handleUrlActions(params);
// 初始化网络监听优化
this.setupNetworkListeners();
},
cacheElements() {
@ -681,6 +717,7 @@
this.elements.deselectAllBtn = document.getElementById('deselect-all-btn');
this.elements.arBtn = document.getElementById('ar-btn');
this.elements.locationCenterBtn = document.getElementById('location-center-btn');
this.elements.resetBtn = document.getElementById('reset-map-btn');
},
bindEvents() {
@ -708,6 +745,11 @@
this.elements.locationCenterBtn.addEventListener('click', () => this.centerToLocation());
}
// 重置地图按钮
if (this.elements.resetBtn) {
this.elements.resetBtn.addEventListener('click', () => this.resetMap());
}
// 页面卸载时清理定位监听
window.addEventListener('beforeunload', () => this.stopLocationTracking());
@ -729,10 +771,66 @@
window.drawModel = this.drawModel.bind(this);
},
/**
* 优化后的网络状态监听:防抖处理,避免频繁闪烁
*/
setupNetworkListeners() {
window.addEventListener('online', () => {
console.log('网络连接已恢复,等待稳定...');
// 清除之前的定时器,防止在不稳定时频繁触发
if (this.state.networkDebounceTimer) {
clearTimeout(this.state.networkDebounceTimer);
}
// 设置防抖等待2秒钟确认网络稳定后再刷新
this.state.networkDebounceTimer = setTimeout(() => {
if (this.map && !this.state.isNetworkRecovering) {
console.log('网络稳定,执行地图刷新');
this.state.isNetworkRecovering = true;
// 记录当前状态
const zoom = this.map.getZoom();
const center = this.map.getCenter();
// 触发瓦片重载的轻微变动 (只变动一点点,减少视觉跳跃)
// 使用 panBy(0,0) 有时无法触发瓦片重载setZoom 是最暴力的有效方法
// 这里使用极其微小的缩放变化,并快速还原
this.map.setZoom(zoom + 0.000001);
setTimeout(() => {
this.map.setZoom(zoom);
this.state.isNetworkRecovering = false;
}, 200);
}
}, 2000); // 2秒防抖时间
});
window.addEventListener('offline', () => {
console.log('网络已断开');
// 如果在等待刷新期间断网,取消刷新
if (this.state.networkDebounceTimer) {
clearTimeout(this.state.networkDebounceTimer);
this.state.networkDebounceTimer = null;
}
});
},
/**
* 重置地图(解决网络差导致的黑屏/闪烁问题)
* 强制刷新当前页面
*/
resetMap() {
console.log('用户请求重置地图...');
// 在 WebGL 地图环境(特别是内嵌 WebView如果因网络问题导致 Context 丢失或瓦片加载卡死,
// 简单的 destroy() 可能不够彻底,直接 location.reload() 是最稳妥的修复方式。
window.location.reload();
},
initMap(projectInfo) {
this.map = new BMapGL.Map('map-container', {
enableHighResolution: true, // 开启高清适配
backgroundColor: [245, 243, 240, 255] // [R, G, B, A] 显式设置 GL 引擎的清屏颜色
backgroundColor: [245, 243, 240, 255] // [R, G, B, A] 显式设置 GL 引擎的清屏颜色与CSS一致
})
const center = projectInfo[0] ? new BMapGL.Point(projectInfo[0].lng, projectInfo[0].lat) : new BMapGL.Point(116.404, 39.915);
this.map.centerAndZoom(center, 12);
@ -760,21 +858,14 @@
}
});
// 网络状态监听(如果运行在 UniApp 环境中)
window.addEventListener('online', () => {
if (App.map) {
// 网络恢复时,稍微缩放一下地图,触发瓦片重新加载,避免卡死在白屏状态
const zoom = App.map.getZoom();
App.map.setZoom(zoom + 0.01);
setTimeout(() => App.map.setZoom(zoom), 100);
}
});
// 注意:原有的 window.addEventListener('online') 已移至 setupNetworkListeners 统一管理
},
/**
* 初始化定位跟踪
*/
initLocationTracking() {
// ... (保持原有代码不变)
// 等待地图加载完成
if (!this.map || !this.state.mapLoaded) {
console.log('等待地图加载完成...');
@ -1071,239 +1162,6 @@
});
},
/**
* 使用uni-app GPS定位WGS84坐标最准确
*/
startUniAppGPSGeolocation() {
console.log('使用uni-app GPS定位WGS84');
// 先获取一次当前位置
uni.getLocation({
type: 'wgs84', // 使用WGS84坐标系GPS原始坐标然后转换为BD09
altitude: false,
geocode: false,
highAccuracyExpireTime: 10000, // 增加等待时间获取GPS定位
success: (res) => {
console.log('uni-app GPS定位成功:', res.longitude, res.latitude, '精度:', res.accuracy);
// uni-app返回的是WGS84坐标需要转换为BD09
this.wgs84ToBd09(res.longitude, res.latitude, (bd09) => {
if (bd09 && bd09.lng && bd09.lat) {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: res.accuracy || 0
};
console.log('GPS坐标转换完成 - BD09:', bd09.lng, bd09.lat);
this.updateLocationMarker();
} else {
console.error('GPS坐标转换失败使用GCJ02定位');
this.startUniAppGeolocation();
}
});
},
fail: (err) => {
console.error('uni-app GPS定位失败:', err);
// 降级到GCJ02定位
this.startUniAppGeolocation();
}
});
// 持续监听位置变化改为每5秒更新一次
this.state.watchLocationTimer = setInterval(() => {
uni.getLocation({
type: 'wgs84',
altitude: false,
geocode: false,
highAccuracyExpireTime: 10000,
success: (res) => {
this.wgs84ToBd09(res.longitude, res.latitude, (bd09) => {
if (bd09 && bd09.lng && bd09.lat) {
// 只更新精度更好的位置
if (!this.state.currentLocation || res.accuracy < this.state.currentLocation.accuracy || res.accuracy < 20) {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: res.accuracy || 0
};
this.updateLocationMarker();
}
}
});
},
fail: (err) => {
console.error('uni-app GPS定位更新失败:', err);
}
});
}, 3000); // 每3秒更新一次
},
/**
* 使用uni-app定位GCJ02坐标
*/
startUniAppGeolocation() {
// 先获取一次当前位置
uni.getLocation({
type: 'gcj02', // 使用GCJ02坐标系火星坐标然后转换为BD09
altitude: false,
geocode: false,
highAccuracyExpireTime: 4000,
success: (res) => {
console.log('uni-app定位成功:', res.longitude, res.latitude, '精度:', res.accuracy);
// uni-app返回的是GCJ02坐标需要转换为BD09
this.gcj02ToBd09(res.longitude, res.latitude, (bd09) => {
if (bd09 && bd09.lng && bd09.lat) {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: res.accuracy || 0
};
console.log('坐标转换完成 - BD09:', bd09.lng, bd09.lat);
this.updateLocationMarker();
} else {
console.error('坐标转换失败,使用备用方案');
// 如果转换失败,尝试使用百度地图定位
if (typeof BMapGL !== 'undefined' && BMapGL.Geolocation) {
this.startBaiduGeolocation();
} else {
this.startBrowserGeolocation();
}
}
});
},
fail: (err) => {
console.error('uni-app定位失败:', err);
// 降级到百度地图定位或浏览器定位
if (typeof BMapGL !== 'undefined' && BMapGL.Geolocation) {
this.startBaiduGeolocation();
} else {
this.startBrowserGeolocation();
}
}
});
// 持续监听位置变化改为每5秒更新一次
this.state.watchLocationTimer = setInterval(() => {
uni.getLocation({
type: 'gcj02',
altitude: false,
geocode: false,
highAccuracyExpireTime: 4000,
success: (res) => {
this.gcj02ToBd09(res.longitude, res.latitude, (bd09) => {
if (bd09 && bd09.lng && bd09.lat) {
// 只更新精度更好的位置
if (!this.state.currentLocation || res.accuracy < this.state.currentLocation.accuracy || res.accuracy < 50) {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: res.accuracy || 0
};
this.updateLocationMarker();
}
}
});
},
fail: (err) => {
console.error('uni-app定位更新失败:', err);
}
});
}, 3000); // 每3秒更新一次位置
},
/**
* 使用5+定位
*/
startPlusGeolocation() {
const geolocation = plus.geolocation;
const options = {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
};
// 获取当前位置
geolocation.getCurrentPosition(
(position) => {
console.log('5+定位成功:', position);
// 5+返回的是WGS84坐标需要转换为BD09
this.wgs84ToBd09(position.coords.longitude, position.coords.latitude, (bd09) => {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: position.coords.accuracy || 0
};
this.updateLocationMarker();
});
},
(error) => {
console.error('5+定位失败:', error);
this.startBrowserGeolocation();
},
options
);
// 持续监听位置变化
this.state.watchPositionId = geolocation.watchPosition(
(position) => {
this.wgs84ToBd09(position.coords.longitude, position.coords.latitude, (bd09) => {
this.state.currentLocation = {
lat: bd09.lat,
lng: bd09.lng,
accuracy: position.coords.accuracy || 0
};
this.updateLocationMarker();
});
},
(error) => {
console.error('5+定位监听错误:', error);
},
options
);
},
/**
* 使用浏览器定位
*/
startBrowserGeolocation() {
if (!navigator.geolocation) {
console.error('浏览器不支持定位');
return;
}
const options = {
enableHighAccuracy: true, // 高精度定位使用GPS
timeout: 20000, // 增加超时时间到20秒确保获取高精度定位
maximumAge: 0 // 不使用缓存,始终获取最新位置
};
console.log('开始浏览器定位,选项:', options);
// 先获取一次当前位置
navigator.geolocation.getCurrentPosition(
(position) => {
console.log('获取到初始位置:', position.coords);
this.updateLocation(position);
},
(error) => {
console.error('获取初始位置失败:', error);
this.handleLocationError(error);
},
options
);
// 持续监听位置变化
this.state.watchPositionId = navigator.geolocation.watchPosition(
(position) => {
console.log('位置更新:', position.coords);
this.updateLocation(position);
},
(error) => {
console.error('位置监听错误:', error);
this.handleLocationError(error);
},
options
);
},
/**
* GCJ02坐标转BD09坐标百度坐标
*/
@ -2139,6 +1997,12 @@
this.state.watchLocationTimer = null;
}
// 清理网络防抖定时器
if (this.state.networkDebounceTimer) {
clearTimeout(this.state.networkDebounceTimer);
this.state.networkDebounceTimer = null;
}
// 清理更新标记的定时器
if (this.updateMarkerTimer !== null) {
cancelAnimationFrame(this.updateMarkerTimer);