/** * 地图点击位置拾取工具 * 解决标记位置偏移问题 */ import * as Cesium from 'cesium' /** * 更准确的地图位置拾取方法 * @param {Cesium.Viewer} viewer - Cesium viewer实例 * @param {Cesium.Cartesian2} clickPosition - 屏幕点击位置 * @returns {Object|null} 返回 {cartesian3: Cesium.Cartesian3, cartographic: Object} 或 null */ export function pickMapPosition(viewer, clickPosition) { if (!viewer || !clickPosition) { return null } let pickedPosition = null try { // 方法1: 尝试使用场景拾取(最准确,考虑地形) const ray = viewer.camera.getPickRay(clickPosition) if (ray) { // 先尝试拾取地形表面 pickedPosition = viewer.scene.globe.pick(ray, viewer.scene) if (!pickedPosition) { // 如果地形拾取失败,使用椭球面拾取作为fallback pickedPosition = viewer.camera.pickEllipsoid(clickPosition, viewer.scene.globe.ellipsoid) } } // 方法2: 如果上述方法都失败,使用椭球面拾取 if (!pickedPosition) { pickedPosition = viewer.camera.pickEllipsoid(clickPosition, viewer.scene.globe.ellipsoid) } if (pickedPosition) { // 转换为地理坐标 const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition) const longitude = Cesium.Math.toDegrees(cartographic.longitude) const latitude = Cesium.Math.toDegrees(cartographic.latitude) const height = cartographic.height return { cartesian3: pickedPosition, cartographic: { longitude, latitude, height, lon: longitude, // 兼容现有代码 lat: latitude // 兼容现有代码 } } } } catch (error) { console.warn('Position picking failed:', error) } return null } /** * 创建标记实体的统一配置 * @param {Object} coordinates - 地理坐标 {lat, lng} * @param {Object} options - 标记选项 * @returns {Object} Cesium实体配置 */ export function createMarkerEntityConfig(coordinates, options = {}) { const { id = 'map-marker', imageUrl = '/src/assets/images/marker-red.svg', width = 32, height = 32, showLabel = true, labelOffset = 40, fontSize = '12pt' } = options const config = { id, billboard: { image: imageUrl, width, height, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 添加像素偏移补偿 pixelOffset: new Cesium.Cartesian2(0, 0), // 禁用深度测试以确保标记总是可见 disableDepthTestDistance: Number.POSITIVE_INFINITY } } if (showLabel) { config.label = { text: `${coordinates.lat.toFixed(6)}, ${coordinates.lng.toFixed(6)}`, font: `${fontSize} sans-serif`, fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.TOP, pixelOffset: new Cesium.Cartesian2(0, labelOffset), heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 确保标签在标记上方 eyeOffset: new Cesium.Cartesian3(0, 0, -100) } } return config }