百度地图修改

This commit is contained in:
cwchen 2026-01-14 10:33:41 +08:00
parent b332137dc3
commit eef16b07ae
2 changed files with 378 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

View File

@ -168,6 +168,24 @@
background: rgba(0, 45, 182, 1);
}
/* 回到定位按钮 */
.location-center-btn {
position: fixed; bottom: 20px; right: 20px;
width: 32px; height: 32px;
background: rgba(255, 255, 255, 0.95) url('./image/position.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;
}
.location-center-btn:hover {
transform: scale(1.1);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}
.location-center-btn:active {
transform: scale(0.95);
}
/* 地图 Label 样式 - 提取至 CSS */
.map-project-label {
color: #002db6 !important;
@ -230,6 +248,9 @@
<div class="model-preview-close" id="close-preview-btn"></div>
<div class="model-preview-ar" id="ar-btn">AR</div>
</div>
<!-- 回到定位按钮 -->
<div class="location-center-btn" id="location-center-btn" title="回到当前位置"></div>
</body>
<script type="text/javascript">
@ -358,14 +379,19 @@
map: null,
overlays: {
markers: [],
models: []
models: [],
locationMarker: null
},
state: {
projectInfo: [],
currentClickedProject: null,
modelList: [],
checkedNodeIds: [],
selectedProjectId: null
selectedProjectId: null,
currentLocation: null,
currentHeading: 0,
watchPositionId: null,
watchOrientationId: null
},
elements: {
panel: null,
@ -393,6 +419,9 @@
// 渲染工程列表
this.renderProjectList();
// 初始化定位功能
this.initLocationTracking();
// 处理 URL Action
this.handleUrlActions(params);
},
@ -405,6 +434,7 @@
this.elements.selectAllBtn = document.getElementById('select-all-btn');
this.elements.deselectAllBtn = document.getElementById('deselect-all-btn');
this.elements.arBtn = document.getElementById('ar-btn');
this.elements.locationCenterBtn = document.getElementById('location-center-btn');
},
bindEvents() {
@ -427,6 +457,14 @@
this.elements.deselectAllBtn.addEventListener('click', () => this.deselectAllNodes());
}
// 回到定位按钮
if (this.elements.locationCenterBtn) {
this.elements.locationCenterBtn.addEventListener('click', () => this.centerToLocation());
}
// 页面卸载时清理定位监听
window.addEventListener('beforeunload', () => this.stopLocationTracking());
// 监听 postMessage
window.addEventListener('message', (e) => {
const data = e.data;
@ -454,6 +492,344 @@
projectInfo.forEach(p => this.addProjectMarker(p));
},
/**
* 初始化定位跟踪
*/
initLocationTracking() {
// 检查浏览器是否支持定位
if (!navigator.geolocation) {
console.warn('浏览器不支持地理定位');
return;
}
// 创建定位标记图标(带方向的箭头)
this.createLocationIcon();
// 开始监听位置变化
this.startWatchingPosition();
// 开始监听设备方向变化
this.startWatchingOrientation();
},
/**
* 创建定位标记图标
*/
createLocationIcon() {
// 创建一个带方向的箭头图标
// 使用 Canvas 绘制一个圆形标记和方向箭头
const canvas = document.createElement('canvas');
canvas.width = 40;
canvas.height = 40;
const ctx = canvas.getContext('2d');
// 绘制圆形背景
ctx.fillStyle = '#3388ff';
ctx.beginPath();
ctx.arc(20, 20, 15, 0, Math.PI * 2);
ctx.fill();
// 绘制白色边框
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(20, 20, 15, 0, Math.PI * 2);
ctx.stroke();
// 绘制方向箭头(默认向上)
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.moveTo(20, 5);
ctx.lineTo(15, 15);
ctx.lineTo(25, 15);
ctx.closePath();
ctx.fill();
// 转换为图片URL
this.locationIconUrl = canvas.toDataURL();
},
/**
* 开始监听位置变化
*/
startWatchingPosition() {
const options = {
enableHighAccuracy: true, // 高精度定位
timeout: 10000,
maximumAge: 0 // 不使用缓存
};
// 先获取一次当前位置
navigator.geolocation.getCurrentPosition(
(position) => this.updateLocation(position),
(error) => this.handleLocationError(error),
options
);
// 持续监听位置变化
this.state.watchPositionId = navigator.geolocation.watchPosition(
(position) => this.updateLocation(position),
(error) => this.handleLocationError(error),
options
);
},
/**
* 更新位置
*/
updateLocation(position) {
const coords = position.coords || position;
const { latitude, longitude, heading, accuracy } = coords;
if (!latitude || !longitude) return;
// 将WGS84坐标转换为百度坐标
const point = new BMapGL.Point(longitude, latitude);
// 使用百度地图的坐标转换(如果需要)
// 注意BMapGL.Point 可以直接使用WGS84坐标但为了更准确建议转换
// 这里先直接使用,如果发现位置偏移,再添加坐标转换
// 保存当前位置(使用原始坐标,转换在显示时处理)
this.state.currentLocation = {
lat: latitude,
lng: longitude,
accuracy: accuracy || 0
};
// 如果有方向信息,更新方向
if (heading !== null && heading !== undefined) {
this.state.currentHeading = heading;
}
// 更新地图上的标记
this.updateLocationMarker();
},
/**
* 更新定位标记
*/
updateLocationMarker() {
if (!this.map || !this.state.currentLocation) return;
const { lng, lat } = this.state.currentLocation;
// 创建百度地图点(百度地图会自动处理坐标转换)
const point = new BMapGL.Point(lng, lat);
// 创建带方向的图标
const icon = this.createRotatedLocationIcon(this.state.currentHeading);
// 如果标记已存在,更新位置和图标
if (this.overlays.locationMarker) {
this.map.removeOverlay(this.overlays.locationMarker);
}
// 创建新标记
this.overlays.locationMarker = new BMapGL.Marker(point, { icon });
this.map.addOverlay(this.overlays.locationMarker);
// 可选:自动跟随定位(取消注释以下代码以启用)
// this.map.setCenter(point);
},
/**
* 回到平板当前位置
*/
centerToLocation() {
if (!this.map) {
console.warn('地图未初始化');
return;
}
// 如果有当前位置,直接定位
if (this.state.currentLocation) {
const { lng, lat } = this.state.currentLocation;
const point = new BMapGL.Point(lng, lat);
this.map.centerAndZoom(point, 18); // 使用较大的缩放级别以便看清当前位置
return;
}
// 如果没有当前位置,尝试获取一次
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
const point = new BMapGL.Point(longitude, latitude);
this.map.centerAndZoom(point, 18);
// 更新当前位置
this.state.currentLocation = {
lat: latitude,
lng: longitude,
accuracy: position.coords.accuracy || 0
};
// 更新标记
this.updateLocationMarker();
},
(error) => {
console.warn('获取当前位置失败:', error);
alert('无法获取当前位置,请检查定位权限设置');
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
}
);
} else {
alert('浏览器不支持定位功能');
}
},
/**
* 创建旋转后的定位图标
*/
createRotatedLocationIcon(heading) {
const canvas = document.createElement('canvas');
canvas.width = 40;
canvas.height = 40;
const ctx = canvas.getContext('2d');
// 保存上下文
ctx.save();
// 移动到中心点
ctx.translate(20, 20);
// 旋转画布heading是相对于正北的角度需要转换为相对于画布的角度
// 百度地图中heading是相对于正北的角度0-360顺时针为正
// 画布中0度是向右需要转换
const rotation = (heading - 90) * Math.PI / 180; // 转换为弧度并调整方向
ctx.rotate(rotation);
// 绘制圆形背景
ctx.fillStyle = '#3388ff';
ctx.beginPath();
ctx.arc(0, 0, 15, 0, Math.PI * 2);
ctx.fill();
// 绘制白色边框
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(0, 0, 15, 0, Math.PI * 2);
ctx.stroke();
// 绘制方向箭头(向上)
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.moveTo(0, -15);
ctx.lineTo(-8, -5);
ctx.lineTo(8, -5);
ctx.closePath();
ctx.fill();
// 恢复上下文
ctx.restore();
// 转换为图片URL
const iconUrl = canvas.toDataURL();
return new BMapGL.Icon(iconUrl, new BMapGL.Size(40, 40), {
anchor: new BMapGL.Size(20, 20)
});
},
/**
* 开始监听设备方向变化
*/
startWatchingOrientation() {
// 绑定方法,确保在事件监听器中能正确访问 this
this.handleOrientation = this.handleOrientation.bind(this);
// 检查是否支持 DeviceOrientationEvent
if (typeof DeviceOrientationEvent !== 'undefined' && typeof DeviceOrientationEvent.requestPermission === 'function') {
// iOS 13+ 需要请求权限
DeviceOrientationEvent.requestPermission()
.then(response => {
if (response === 'granted') {
window.addEventListener('deviceorientation', this.handleOrientation);
}
})
.catch(console.error);
} else if (window.DeviceOrientationEvent) {
// 其他设备直接监听
window.addEventListener('deviceorientation', this.handleOrientation);
} else {
// 如果不支持,尝试使用 Compass APIuni-app
if (typeof plus !== 'undefined' && plus.compass) {
this.state.watchOrientationId = plus.compass.watchHeading(
(heading) => {
this.state.currentHeading = heading.magneticHeading;
this.updateLocationMarker();
},
(error) => console.error('获取方向失败:', error),
{ frequency: 100 }
);
}
}
},
/**
* 处理设备方向变化
*/
handleOrientation(event) {
// alpha: 绕Z轴旋转指南针方向0-360度
if (event.alpha !== null && event.alpha !== undefined) {
this.state.currentHeading = event.alpha;
this.updateLocationMarker();
}
},
/**
* 处理定位错误
*/
handleLocationError(error) {
let message = '定位失败: ';
switch(error.code) {
case error.PERMISSION_DENIED:
message += '用户拒绝了定位请求';
break;
case error.POSITION_UNAVAILABLE:
message += '位置信息不可用';
break;
case error.TIMEOUT:
message += '定位请求超时';
break;
default:
message += '未知错误';
break;
}
console.warn(message);
},
/**
* 停止定位跟踪
*/
stopLocationTracking() {
// 停止位置监听
if (this.state.watchPositionId !== null) {
navigator.geolocation.clearWatch(this.state.watchPositionId);
this.state.watchPositionId = null;
}
// 停止方向监听
if (typeof plus !== 'undefined' && plus.compass && this.state.watchOrientationId !== null) {
plus.compass.clearWatch(this.state.watchOrientationId);
this.state.watchOrientationId = null;
}
// 移除方向事件监听
window.removeEventListener('deviceorientation', this.handleOrientation);
// 移除定位标记
if (this.overlays.locationMarker && this.map) {
this.map.removeOverlay(this.overlays.locationMarker);
this.overlays.locationMarker = null;
}
},
addProjectMarker(info) {
if (!info.lng || !info.lat) return;