From 105b3296afe787625e0a3d4a0d4bdf7d017045bb Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Thu, 13 Nov 2025 17:55:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(map):=20=E6=B7=BB=E5=8A=A0=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=20billboard=20=E5=AE=9E=E4=BD=93=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在实体服务中添加一个新的异步方法 `addBillboard`,支持在地图中创建并添加广告牌实体。该方法支持可配置选项,包括位置、图像、尺寸、贴合度和像素偏移量,以增强地图可视化效果。 --- .../src/map/services/createEntityService.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/packages/screen/src/map/services/createEntityService.js b/packages/screen/src/map/services/createEntityService.js index c5ac8dc..08e8bb0 100644 --- a/packages/screen/src/map/services/createEntityService.js +++ b/packages/screen/src/map/services/createEntityService.js @@ -95,6 +95,86 @@ export function createEntityService(deps) { return id }, + /** + * 添加广告牌(Billboard)实体到地图 + * @param {Object} opts - 配置选项 + * @param {string} [opts.id] - 实体 ID,不提供则自动生成 + * @param {string} [opts.layerId] - 图层 ID,不提供则使用默认图层 + * @param {Array} opts.position - 位置 [经度, 纬度] 或 [经度, 纬度, 高度],高度默认为 0 + * @param {string} opts.image - 图片 URL 或路径 + * @param {number} [opts.width=32] - 图片宽度(像素) + * @param {number} [opts.height=32] - 图片高度(像素) + * @param {boolean} [opts.clampToGround=true] - 是否贴地 + * @param {Cesium.VerticalOrigin} [opts.verticalOrigin] - 垂直对齐方式 + * @param {Array|Cesium.Cartesian2} [opts.pixelOffset] - 像素偏移 [x, y] + * @param {number} [opts.disableDepthTestDistance] - 禁用深度测试的距离 + * @param {Object} [opts.properties] - 自定义属性 + * @returns {Promise} 返回实体 ID + */ + async addBillboard(opts) { + const o = opts || {} + + // 验证必需参数 + if (!Array.isArray(o.position) || o.position.length < 2) { + throw new Error('addBillboard 需要提供 position 参数 [经度, 纬度] 或 [经度, 纬度, 高度]') + } + + const image = o.image || o.icon + if (!image) { + throw new Error('addBillboard 需要提供 image 或 icon 参数') + } + + // 确保 position 包含高度,如果没有则默认为 0 + const position = o.position.length === 2 + ? [o.position[0], o.position[1], 0] + : o.position + + const ds = await this._ensureVectorLayer(o.layerId) + const id = o.id || uid('billboard') + + // 处理像素偏移 + let pixelOffset + if (o.pixelOffset instanceof Cesium.Cartesian2) { + pixelOffset = o.pixelOffset + } else if (Array.isArray(o.pixelOffset)) { + pixelOffset = new Cesium.Cartesian2( + o.pixelOffset[0] || 0, + o.pixelOffset[1] || 0 + ) + } else if (o.pixelOffset && typeof o.pixelOffset === 'object') { + pixelOffset = new Cesium.Cartesian2( + o.pixelOffset.x || 0, + o.pixelOffset.y || 0 + ) + } else { + pixelOffset = new Cesium.Cartesian2(0, 0) + } + + const ent = new Cesium.Entity({ + id, + position: degToCartesian(position), + billboard: { + image, + width: o.width || 32, + height: o.height || 32, + verticalOrigin: o.verticalOrigin || Cesium.VerticalOrigin.BOTTOM, + heightReference: + o.clampToGround === false + ? Cesium.HeightReference.NONE + : Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: + typeof o.disableDepthTestDistance === 'number' + ? o.disableDepthTestDistance + : Number.POSITIVE_INFINITY, + pixelOffset, + }, + properties: o.properties || {}, + }) + + ds.entities.add(ent) + return id + }, + removeEntity(entityId) { if (!entityId) return false for (const id in store.layers) {