Appearance
Action Renderer(动作渲染器系统)
动作渲染器系统提供一种声明式的动作执行框架:将动作定义为数据(Action),由对应的渲染器(ActionRenderer)在 Cesium 场景中执行可视化。系统基于观察者模式,通过注册中心管理各类渲染器。
Action 接口
typescript
interface Action {
id: string // 唯一标识
type: string // 动作类型(如 'MoveTo', 'TLEOrbit')
entityId: string // 目标实体 ID
name?: string // 动作名称(可选)
startTime?: number // 开始时间(epoch 毫秒)
endTime?: number // 结束时间(epoch 毫秒)
parameters: Record<string, unknown> // 动作参数(类型相关)
}ActionRenderContext 接口
typescript
interface ActionRenderContext {
viewer: Viewer // Cesium Viewer 实例
}渲染器通过 context 访问 Viewer 和场景数据。
ActionRenderer 接口
所有渲染器需实现此接口:
typescript
interface ActionRenderer {
readonly type: string // 渲染器类型标识
create(action: Action, context: ActionRenderContext): void // 创建动作可视化
update(action: Action, context: ActionRenderContext): void // 更新动作
destroy(actionId: string): void // 销毁动作
}ActionRendererRegistry(注册中心)
单例模式,全局共享:
typescript
import { actionRendererRegistry } from './ActionRendererRegistry'
// 注册渲染器
actionRendererRegistry.register('MoveTo', new MoveToRenderer())
// 获取渲染器
const renderer = actionRendererRegistry.get('TLEOrbit')
// 检查是否已注册
if (actionRendererRegistry.has('MissileStrike')) { /* ... */ }
// 注销渲染器
actionRendererRegistry.unregister('MoveTo')内置渲染器
1. MoveToRenderer(type: 'MoveTo')
实体平滑移动渲染器。支持从起点移动到终点的过程动画,在 startTime 到 endTime 内完成插值。
参数类型: { from?: { lon, lat, alt }, to: { lon, lat, alt } }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
from | { lon, lat, alt } | 否 | 起始位置,省略则使用实体当前位置 |
to | { lon, lat, alt } | 是 | 目标位置 |
行为说明:
- 当
startTime或endTime为空时执行瞬移 - 支持多个动作叠加到同一实体(自动合并轨迹)
- 实体位置使用
SampledPositionProperty驱动
示例:
typescript
const action: Action = {
id: 'move-001',
type: 'MoveTo',
entityId: 'aircraft-1',
startTime: Date.now(),
endTime: Date.now() + 5000,
parameters: {
from: { lon: 116.4, lat: 39.9, alt: 1000 },
to: { lon: 116.5, lat: 40.0, alt: 2000 }
}
}2. TLEOrbitRenderer(type: 'TLEOrbit')
基于 TLE 轨道根数的卫星轨道渲染器。使用 SatelliteOrbitTool 计算轨道传播,驱动实体沿轨道运动。
参数类型: { tleLine1: string, tleLine2: string, step?: number }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
tleLine1 | string | 是 | TLE 第一行 |
tleLine2 | string | 是 | TLE 第二行 |
step | number | 否 | 采样步长(秒),默认 60 |
行为说明:
- 自动计算
startTime到endTime范围内的轨道轨迹 - 自动为实体添加
VelocityOrientationProperty速度朝向 - 支持多个 TLEOrbit 动作叠加到同一实体
示例:
typescript
const action: Action = {
id: 'tle-001',
type: 'TLEOrbit',
entityId: 'satellite-1',
name: 'ISS',
startTime: Date.now(),
endTime: Date.now() + 3600000, // 1 小时
parameters: {
tleLine1: '1 25544U 98067A 24123.51782528 .00016717 00000-0 10270-4 0 9001',
tleLine2: '2 25544 51.6414 80.5114 0006702 89.1582 271.0270 15.50367711452180',
step: 30
}
}3. MissileStrikeRenderer(type: 'MissileStrike')
导弹打击动画渲染器。支持直线轨迹和弹道轨迹两种模式。
参数类型:
typescript
{
missileUri?: string // 导弹模型 URL(可选)
targetType?: 'entity' | 'point' // 目标类型
targetEntityId?: string // 目标实体 ID
targetPoint?: { lon: number; lat: number; alt?: number } // 目标坐标点
trajectory?: 'line' | 'ballistic' // 轨迹类型
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
missileUri | string | 否 | 3D 模型地址,省略则只显示路径 |
targetType | 'entity' | 'point' | 否 | 目标类型 |
targetEntityId | string | 否 | 动态目标实体 ID |
targetPoint | object | 否 | 静态目标坐标点 |
trajectory | 'line' | 'ballistic' | 否 | 轨迹类型,默认 'line' |
轨迹计算:
'line'— 线性插值轨迹'ballistic'— 贝塞尔曲线弹道轨迹(峰值高度 150km)
示例:
typescript
const action: Action = {
id: 'strike-001',
type: 'MissileStrike',
entityId: 'launcher-1',
startTime: Date.now(),
endTime: Date.now() + 10000,
parameters: {
missileUri: '/models/missile.gltf',
targetType: 'point',
targetPoint: { lon: 120.5, lat: 30.5, alt: 0 },
trajectory: 'ballistic'
}
}自定义渲染器
实现自定义渲染器只需实现 ActionRenderer 接口并注册:
typescript
import { actionRendererRegistry } from '../ActionRendererRegistry'
import type { Action, ActionRenderer, ActionRenderContext } from '../action-renderers'
class RadarScanRenderer implements ActionRenderer {
readonly type = 'RadarScan'
create(action: Action, context: ActionRenderContext): void {
const entity = context.viewer.entities.getById(action.entityId)
if (!entity) return
// 创建雷达扫描可视化...
console.log(`RadarScan: ${action.entityId}`, action.parameters)
}
update(action: Action, context: ActionRenderContext): void {
this.destroy(action.id)
this.create(action, context)
}
destroy(actionId: string): void {
// 清理资源...
}
}
// 注册自定义渲染器
actionRendererRegistry.register('RadarScan', new RadarScanRenderer())使用内置渲染器
typescript
import { actionRendererRegistry } from './ActionRendererRegistry'
import { MoveToRenderer } from './renderers/MoveToRenderer'
import { TLEOrbitRenderer } from './renderers/TLEOrbitRenderer'
import { MissileStrikeRenderer } from './renderers/MissileStrikeRenderer'
// 注册内置渲染器
actionRendererRegistry.register('MoveTo', new MoveToRenderer())
actionRendererRegistry.register('TLEOrbit', new TLEOrbitRenderer())
actionRendererRegistry.register('MissileStrike', new MissileStrikeRenderer())
// 执行动作
const renderer = actionRendererRegistry.get('MoveTo')
if (renderer) {
renderer.create(moveAction, { viewer })
}