Skip to content

glTF 模型编辑

使用 EntityTransformEditor 编辑由 viewer.createEntity() 创建的装备位置、航向和缩放。

概述

EntityTransformEditor 是 entities 子系统的交互能力,负责模型选择、拖动预览和变换提交。它不会创建或删除装备;装备生命周期继续由 viewer.createEntity()EntityManager 统一管理。

  • 单击已管理装备后显示可恢复的黄色轮廓。
  • 按住已选装备拖动,松开时只向 EntityManager 提交一次位置更新。
  • 通过 API 调整航向角与模型缩放。
  • 取消、禁用或销毁时恢复未提交位置、相机控制、鼠标样式、装备显隐和原轮廓。
  • 深度取点不可用时依次回退到地球射线拾取与椭球拾取。

快速开始

ts
import {
  CesiumViewer,
  EntityTransformEditor,
  viewerEntityMixin,
} from '@nexa/gis-cesium'

const nexaGis = new CesiumViewer('container')
nexaGis.extend(viewerEntityMixin)

// 装备必须通过统一入口创建。
const equipment = nexaGis.viewer.createEntity({
  id: 'vehicle-01',
  name: '保障车辆',
  entityType: 'vehicle',
  components: [
    { id: 'position', type: 'PositionComponent', lon: 106.45, lat: 29.50, alt: 0 },
    { id: 'orientation', type: 'OrientationComponent', heading: 45, pitch: 0, roll: 0 },
    { id: 'model', type: 'ModelComponent', url: '/static/GroundVehicle.glb', scale: 1.2 },
  ],
  modules: [],
})

const editor = new EntityTransformEditor({
  viewer: nexaGis.viewer,
  entityManager: nexaGis.viewer.entityManager,
})

editor.select(equipment)
editor.setHeading(90)
editor.setScale(1.5)

// 页面卸载时只销毁编辑器;装备仍由 EntityManager 所有。
editor.destroy()

EntityManager.updateTransform

ts
const changed = viewer.entityManager.updateTransform('vehicle-01', {
  position: Cesium.Cartesian3.fromDegrees(106.46, 29.51, 20),
  heading: 120,
  pitch: 0,
  roll: 0,
  scale: 1.8,
})

该方法会先校验完整补丁,再同步 ScenarioEntity 组件与 Cesium Entity,最后只发出一次 update 事件。未知装备返回 false;空补丁、非有限角度、非正缩放或无模型装备的缩放请求会抛出明确错误。

位置写入 PositionComponent 时统一转换为 WGS84 经纬高。位置变化后,已有 OrientationComponent 会以新位置的 ENU 参考系重新计算四元数,避免拖动后航向沿用旧参考系。

EntityTransformPatch

字段类型说明
positionCesium.Cartesian3ECEF 世界坐标
headingnumber航向角(度)
pitchnumber俯仰角(度)
rollnumber横滚角(度)
scalenumber模型统一缩放,必须大于 0

EntityTransformEditor

构造选项

参数类型默认值说明
viewerCesium.Viewer-Cesium Viewer
entityManagerEntityManager-装备所属管理器
enabledbooleantrue是否立即启用
highlightColorCesium.ColorColor.YELLOW选择轮廓颜色
highlightSizenumber3选择轮廓宽度
positionPicker(screen) => Cartesian3 | undefined内置三级回退自定义取点策略
onSelect(entity) => void-选择变化回调
onChange(event) => void-已提交变换回调

方法和状态

API说明
selectedEntity当前选中的 CombatEntity
isDragging当前是否正在拖动
select(entity)选择当前管理器中的装备;传 undefined 清除
setHeading(degrees)更新选中装备航向角
setScale(scale)更新选中装备缩放
cancelDrag()回滚未提交拖动
enable() / disable()幂等启用或禁用交互
destroy()完整释放监听、临时点和引用,不删除装备

onChangesourcedragapi,便于调用方区分鼠标提交和面板提交。

生命周期与所有权

ts
const equipmentIds = new Set<string>()
const equipment = viewer.createEntity(data)
equipmentIds.add(equipment.id)

const editor = new EntityTransformEditor({ viewer, entityManager: viewer.entityManager })

// 卸载顺序:先释放交互,再由装备创建方移除自己的装备。
editor.destroy()
for (const id of equipmentIds) viewer.entityManager.remove(id)

编辑器内部唯一创建的 Entity 是拖动期间的临时点,并会在松开、取消、禁用或销毁时移除。不要用 viewer.entities.removeAll() 清理案例,它会误删其他模块的实体。

浏览器验收

  1. 打开“glTF 模型编辑”,确认三件模型均显示且默认选中“保障车辆 A”。
  2. 单击另一个模型,确认黄色轮廓切换,前一个模型恢复原轮廓。
  3. 按住已选模型拖动并松开,确认模型落到新位置,面板状态结束“正在拖动”。
  4. 拖动途中右键取消,确认模型回到拖动前位置,相机旋转、平移和倾斜状态恢复。
  5. 调整航向与缩放滑块,确认姿态和尺寸实时更新;拖动后再次调整航向仍绕新位置的 ENU 参考系。
  6. 点击“恢复初始变换”,确认位置、航向与缩放一并恢复。
  7. 离开案例再返回,确认没有残留临时点、黄色轮廓、鼠标样式或重复监听。

注意事项

  • 模型装备必须由 viewer.createEntity() 创建,编辑器拒绝选择其他 EntityManager 的对象。
  • pickPosition 的结果可能是模型表面而非地面;需要固定地形高度时可通过 positionPicker 注入业务取点策略。
  • 大量模型的批量编辑不属于本编辑器目标;超过约百级装备时应评估 Primitive 和批处理方案。
  • 编辑器使用 ModelGraphics 的公开轮廓属性,不依赖 Cesium 私有字段。

相关链接