Appearance
HTML div 点标注(DivPointLayer)
在 Viewer 容器上叠加一个 DOM 覆盖层图层,把任意 HTML 内容(富卡片、状态面板、图表、 徽标)持续锚定到地理坐标:每帧随
scene.postRender把世界坐标投影到屏幕像素刷新位置, 相机拉远到视高超过阈值后自动隐藏。适合大屏 / 监控台的高密度业务标注。
能力定位
DivPointLayer 适合:
- 监测站点卡片:名称 + 实时数据面板(流量 / 液位 / 状态徽标)锚定到设备位置;
- 大屏态势标注:复杂 DOM 标记(图表、状态徽标、富文本说明)跟随相机但不必绘制为 Cesium 几何体;
- 批量管理:支持批量
addPoint、单点remove、整层removeAll与hide/show显隐。
与相关能力的分工:
| 能力 | 形态 | 差异 |
|---|---|---|
DivPointLayer | 任意 HTML 覆盖层标注图层 | 通用、批量、每点任意 HTML,支持动态更新位置 |
AnimatePointEffect | 单点脉冲涟漪效果 | 只有圆点扩散,无 HTML 内容 |
PopupManager | 点击弹窗 | 事件驱动、单例弹窗,非图层化标注 |
BillboardGifEffect | 图标点 GIF 动效 | WebGL billboard 渲染,非 DOM |
构造函数
ts
constructor(options?: DivPointLayerOptions)ts
interface DivPointLayerOptions {
hideHeight?: number // 相机视高超过该阈值(米)后隐藏全部标注点,默认 14000
}| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
hideHeight | number | 14000 | 视点高度(米)超过该值时隐藏全部标注点,拉近后自动恢复(对齐源案例行为) |
生命周期
实现 Lifecycle<Viewer> 契约,on/off/destroy 均幂等:
ts
on(viewer: Viewer): void // 创建图层容器 + 注册 scene.postRender 逐帧投影
off(viewer: Viewer): void // 移除监听 + 图层容器 + 全部标注点(幂等,可再次 on)
destroy(viewer: Viewer): void // 等价于 off(幂等)清理完整性:本类只拥有自身创建的图层容器 DOM、各标注点 DOM 与 scene.postRender 监听,off/destroy 一并移除,不触碰调用方其他资源。
基础示例
ts
import { DivPointLayer } from '@nexa/gis-cesium'
const layer = new DivPointLayer({ hideHeight: 14000 })
layer.on(viewer) // 挂载图层,开始逐帧投影
const marker = layer.addPoint({
position: Cesium.Cartesian3.fromDegrees(116.274028, 30.978035, 944.63),
content: '<div class="my-card">明山泉水</div>',
})
marker.element // 标注点根 DOM,可追加样式 / 事件
marker.position // 当前世界坐标的独立副本
marker.updatePosition(nextPosition) // 拖拽/数据更新后改变锚定位置
marker.remove() // 移除该标注点
layer.hide() // 临时隐藏全部标注点(DOM 保留)
layer.show() // 重新显示
// 页面或场景退出时统一清理(幂等)
layer.destroy(viewer)进阶示例
批量添加富卡片标注,并演示内容函数的三种写法:
ts
const layer = new DivPointLayer()
layer.on(viewer)
// content 支持三种形式:字符串(innerHTML)/ HTMLElement / 函数(挂载时调用一次)
layer.addPoint({ position: p1, content: '<div>字符串内容</div>' })
const el = document.createElement('div')
el.textContent = 'DOM 元素内容'
layer.addPoint({ position: p2, content: el })
layer.addPoint({
position: p3,
content: () => `<div>函数内容,${new Date().toLocaleTimeString()}</div>`,
})
// 单点移除
const marker = layer.addPoint({ position: p4, content: '<div>待移除</div>' })
marker.remove()
// 整层清空
layer.removeAll()动态位置与编辑
DivPointMarker.position 返回坐标副本,外部修改不会绕过图层状态。位置变更必须通过 updatePosition 提交,新位置会在下一次 postRender 投影中生效:
ts
const marker = layer.addPoint({ position, content: card })
dragHandler.onMove((screenPosition) => {
const nextPosition = viewer.scene.pickPosition(screenPosition)
if (nextPosition) marker.updatePosition(nextPosition)
})
// 已 remove 的 marker 不会因 updatePosition 重新挂载,重复调用安全
marker.remove()
marker.updatePosition(nextPosition)绘制、选中、拖拽与 GeoJSON 持久化的完整组合用法见 HTML 标注绘制与编辑。
实现说明
- 投影 API:每帧通过公共
SceneTransforms.worldToWindowCoordinates(scene, position)把 世界坐标投影到屏幕像素,刷新left与bottom(bottom = canvasHeight - y)。源案例使用的wgs84ToWindowCoordinates在目标 Cesium 1.133 已移除,本实现已迁移。 - 高度裁剪:通过
scene.globe.ellipsoid.cartesianToCartographic(camera.position).height计算视点高度,超过hideHeight(默认 14000 米)隐藏全部标注点,拉近后恢复(对齐源案例PointObject/DivPoint的camera.positionCartographic.height > 14000行为)。 - 投影不可见处理:投影返回
undefined(点位于相机后方等情形)时隐藏该标注点。 - 指针穿透:图层容器
pointer-events: none不遮挡 canvas 交互;标注点本身pointer-events: auto可接收鼠标事件。 - 位置快照:
position返回Cartesian3副本;updatePosition同样克隆输入, 避免调用方之后就地修改对象导致图层状态无法追踪。 - 源案例缺陷修复:源实现逐点注册
postRender监听且windowClose只置空 DOM 不移除; 本实现改为单图层统一监听 +Lifecycle幂等 on/off/destroy 完整清理。 - 公共 API:仅使用 Cesium 公共
SceneTransforms.worldToWindowCoordinates、Ellipsoid.cartesianToCartographic与scene.postRender,不触碰私有字段。 - 无外部依赖:源案例的 Vue 组件 / element-ui tooltip / 外网地形与底图等 demo 编排迁移时 剥离,标注内容以纯 HTML 字符串 / DOM 呈现,使用 SDK 默认底图与示例区域视角。
清理责任
ts
layer.destroy(viewer) // 或 layer.off(viewer),等价且幂等重复调用 destroy/off 安全(未 on 时为空操作)。销毁后重新 on 可再次挂载。
Cesium 版本限制
- 依赖 Cesium 公共
SceneTransforms.worldToWindowCoordinates/Ellipsoid.cartesianToCartographic/Scene.postRender; - 已验证目标版本:Cesium 1.133.1。