Skip to content

AnimatePointEffect 动画点位效果

在指定经纬度位置上叠加一个带脉冲涟漪动画的 DOM 圆点标记。基于 scene.postRender 每帧将世界坐标投影为屏幕坐标并刷新 DOM 位置,形成持续扩散的涟漪效果。


能力定位

AnimatePointEffect 适合:

  • 重点点位标记:目标、兴趣点、事件位置;
  • 大屏态势展示:多点位定位涟漪,突出关注目标;
  • 与实体配合:作为 DOM overlay 叠加在 Cesium 实体之上,不占用 GPU 资源。

特效系统 中的实体类效果不同,本效果使用 DOM overlay,通过 注入的 @keyframes 动画实现涟漪,适合数量较少、需要自定义 CSS 外观的点位。

构造函数

ts
constructor(options: AnimatePointEffectOptions)
ts
interface AnimatePointEffectOptions {
  position: Cartesian3;      // 点位位置(世界坐标),必填
  cssColor?: string;         // CSS 颜色,默认 '#ff0000'
  maxVisibleHeight?: number; // 相机高度超过该值后隐藏(米),默认 80000
}
参数类型默认值描述
positionCartesian3点位世界坐标,缺少时构造抛错
cssColorstring'#ff0000'点位及涟漪颜色,任意合法 CSS 颜色值
maxVisibleHeightnumber80000相机高度超过该阈值后隐藏点位,避免高空视角下 DOM 标记失去意义

生命周期

ts
on(viewer: Viewer): void      // 启用效果,创建 DOM 与样式,注册 postRender 监听(幂等)
off(viewer: Viewer): void     // 停用效果,移除监听、DOM 与注入的样式(幂等)
destroy(viewer: Viewer): void // 销毁效果,委托 off 释放全部自有资源(可重复调用)
方法参数说明
onviewer重复调用为 no-op,不会重复创建资源
offviewer未启用时调用为 no-op
destroyviewer委托 off,重复调用安全

基础示例

ts
import { AnimatePointEffect } from '@nexa/gis-cesium'
import { Cartesian3 } from 'cesium'

const effect = new AnimatePointEffect({
  position: Cartesian3.fromDegrees(118.76, 32.03, 0),
  cssColor: '#ff0000',
})

effect.on(viewer)

// 页面或场景退出时由创建方负责清理
effect.destroy(viewer)

进阶示例

多点位、多颜色标记,模拟城市态势分布:

ts
import { AnimatePointEffect } from '@nexa/gis-cesium'
import { Cartesian3 } from 'cesium'

const positions = [
  { lng: 118.76, lat: 32.03, color: '#ff0000' },
  { lng: 118.78, lat: 32.05, color: '#ffa500' },
  { lng: 118.72, lat: 32.01, color: '#00ff7f' },
]

const effects = positions.map(({ lng, lat, color }) => {
  const fx = new AnimatePointEffect({
    position: Cartesian3.fromDegrees(lng, lat, 0),
    cssColor: color,
  })
  fx.on(viewer)
  return fx
})

// 场景退出时统一清理
effects.forEach(fx => fx.destroy(viewer))

可见性规则

与源案例一致,点位只在满足以下两个条件时显示:

  1. 相机到点位的距离 ≤ 相机高度 + 地球最大半径(避免点位在地球背面时仍显示);
  2. 相机高度 < maxVisibleHeight(默认 80000 米)。
ts
const carto = viewer.scene.globe.ellipsoid.cartesianToCartographic(viewer.camera.position)
const cameraHeight = carto ? carto.height : 0
const distance = Cesium.Cartesian3.distance(viewer.camera.position, this._position)
const visible =
  distance <= cameraHeight + viewer.scene.globe.ellipsoid.maximumRadius &&
  cameraHeight < this._maxVisibleHeight

实现与性能说明

  • DOM overlay:效果在 viewer.cesiumWidget.container 上叠加绝对定位的 divpointer-events: none 穿透,不阻挡场景交互;
  • 样式注入:涟漪动画的 @keyframes 按实例生成唯一名称并注入 <style>off() 时移除。多个效果可并存互不干扰,无需宿主页面引入外部 CSS;
  • 坐标投影:使用 SceneTransforms.worldToWindowCoordinates(Cesium 1.133 已移除 旧版 wgs84ToWindowCoordinates);
  • 资源所有权:效果只创建并释放自己的 DOM 节点、注入样式与 postRender 监听, 不触碰 viewer 实体或图层。

Cesium 版本限制

  • 需要 Cesium ≥ 1.100(SceneTransforms.worldToWindowCoordinates 可用);
  • 已验证目标版本:Cesium 1.133.1。

清理责任

  • on() 创建的 DOM、样式与监听,统一由 destroy(viewer)(或 off(viewer))释放;
  • 不调用 destroy 会导致 postRender 监听与 DOM 残留,务必在页面或场景退出时清理;
  • destroy 可重复调用,幂等安全。

与原生 Cesium API 的组合方式

  • 可与 viewer.entities.add() 的 point/label 实体叠加使用,作为实体位置的醒目 DOM 标记;
  • 需要跟随场景其他元素时,直接创建多个 AnimatePointEffect 实例即可,无共享状态。