地图修改
This commit is contained in:
parent
0e36e947d0
commit
66c33586d6
Binary file not shown.
|
After Width: | Height: | Size: 904 B |
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue