npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cesium-path-animation

v0.1.3

Published

适配 Cesium 1.107.2 到 1.128.0 的模型路径动画与相机跟随控制器

Readme

cesium-path-animation

基于 Cesium 1.107.2 到 1.128.0 的模型路径动画与相机控制器。暴露单个类 CesiumPathAnimation,提供 3D 模型加载、路径动画、三种相机跟随模式、粒子管理、模型初始化管理、模型辉光、循环播放等能力。demo 默认使用 demo/demo.gltf,并在海口附近创建两个首尾相连的巡检对象,方便观察多对象同时工作状态。

安装

npm install cesium-path-animation
# cesium 为 peerDependency,需宿主项目自行安装;Node 16 推荐使用 1.107.2
npm install [email protected]

快速开始

import { CesiumPathAnimation, CAMERA_MODE, PATH_MODE } from 'cesium-path-animation'

const viewer = new Cesium.Viewer('cesiumContainer')

const anim = new CesiumPathAnimation({
  viewer,
  model: {
    url: '/model/plane.glb',
    scale: 20,
    brightness: 1,
    orientation: { heading: 0, pitch: 0, roll: 0 }
  },
  path: {
    name: '演示路径',
    mode: PATH_MODE.LINEAR,
    speed: 120,
    points: [
      { lon: 110.303, lat: 20.03, height: 1000 },
      { lon: 110.354, lat: 20.035, height: 1200 },
      { lon: 110.401, lat: 20.04, height: 1500 }
    ]
  },
  speed: 2,
  camera: {
    mode: CAMERA_MODE.THIRD_PERSON,
    distance: 5000,
    angle: { heading: 0, pitch: Cesium.Math.toRadians(-26) },
    autoOrbit: true
  },
  particle: {
    enabled: true,
    color: '#c7ffbb',
    imageSize: 12,
    particleLife: 2,
    backOffset: 19,
    sideOffset: 0
  },
  glow: { enabled: true, color: '#00ff66', sizeMeters: 180 },
  loop: true,
  trajectoryVisible: true,
  autoplay: true
})

// 后续仍可随时动态调整
anim.setSpeed(3)
anim.setCameraMode(CAMERA_MODE.FIXED)
anim.setLoop(false)

构造参数

| 参数 | 类型 | 说明 | | --- | --- | --- | | viewer | Cesium.Viewer | 必填,已创建的 Cesium Viewer 实例 | | console | boolean \| object | 可选,是否显示共享控制台,也可传 { label, id, enabled } | | model | string \| object | 可选,初始模型;字符串等同模型 URL,对象支持 { url, scale, brightness, orientation, ...ModelGraphicsOptions } | | path | Array \| object | 可选,初始路径;支持点数组或 { name, mode, speed, closedLoop, points } | | speed | number | 可选,初始播放倍率 | | camera | object | 可选,初始相机配置;支持 { mode, distance, angle, autoOrbit, autoOrbitSpeed, fixedTarget } | | followTarget | Entity \| Model \| object \| function | 可选,相机跟随目标;不传时默认跟随插件内部模型,支持外部 Entity、Cesium.Model、ModelInstanceCollection 指定实例或自定义位置函数 | | particle | boolean \| object | 可选,初始粒子配置;对象支持 { enabled, color, imageSize, particleLife, backOffset, sideOffset } | | glow | boolean \| string \| object | 可选,初始辉光配置;字符串等同辉光颜色,对象支持 { enabled, color, sizeMeters } | | loop | boolean | 可选,是否循环播放 | | returnMotion | boolean | 可选,是否折返运动 | | trajectoryVisible | boolean | 可选,是否显示轨迹线 | | pathEditor | boolean | 可选,是否开启地图路径编辑 | | autoplay | boolean | 可选,实例化完成后是否立即播放 |

构造参数会在实例化阶段一次性应用;实例创建后,仍可继续使用 setModelsetPathsetSpeedsetCameraModesetParticleEnabled 等方法动态调整。也可以调用 applyOptions(options) 批量更新同一套配置。

API

| 方法 | 说明 | | --- | --- | | applyOptions(options) | 批量应用初始化配置;可在实例化后继续一次性更新模型、路径、相机、跟随目标、粒子、辉光、循环和播放状态 | | setFollowTarget(target) | 设置相机跟随目标;支持外部 Entity、Cesium.Model、ModelInstanceCollection 指定实例或自定义位置函数,传 null 恢复跟随插件内部模型 | | setModel(url, options?) | 设置 3D 模型文件路径;会按模型名自动读取本地模型初始化设置 | | setLocalModelFile(file, options?) | 使用用户本地选择的 .glb / .gltf 模型文件,当前页面立即生效 | | setModelScale(scale) | 设置模型初始缩放,有效范围 0.00110000;控制台滑块使用换算映射,方便调节极小值;会按模型名自动保存 | | setModelBrightness(brightness) | 设置模型亮度倍数,有效范围 0.110,默认 1;会按模型名自动保存。底层写入 Cesium 的 imageBasedLightingFactor 会自动限制在 01,避免不同 Cesium 版本渲染时报错 | | setModelOrientation({ heading, pitch, roll }) | 设置模型初始朝向偏移(弧度),修正模型自身朝向与运动方向不一致;会按模型名自动保存 | | setPath(pointsOrConfig) | 设置当前路径。既支持直接传点数组,也支持传 { name, mode, speed, closedLoop, points } 一次性覆盖整条路径配置 | | setPathMode(mode) | 设置轨迹模式:PATH_MODE.LINEAR / PATH_MODE.BEZIER | | addPathPoint(point, time?) | 动态追加一个路径点 | | setPathSpeed(metersPerSecond) | 设置路径推算速度(米/秒),仅影响缺省时间的点 | | setSpeed(multiplier) | 设置插件自身播放速度倍率;基于宿主 viewer.clock 的时间推进额外叠加,不改宿主倍率 | | setCameraMode(mode) | 切换相机视角,见 CAMERA_MODE | | setCameraDistance(distance) | 设置相机与模型距离(米) | | setCameraAngle({ heading, pitch }) | 设置相机角度(弧度) | | play() | 播放动画 | | pause() | 暂停动画 | | setParticleEnabled(enabled, options?) | 开启/关闭粒子发射器,默认从路径运动点发射,支持 color / startColor / endColor / imageSize / particleLife / backOffset / sideOffsetbackOffset 为前后偏移米数,正数在运动点后方,负数在运动点前方;sideOffset 为左右偏移米数,正数在运动点右侧,负数在运动点左侧;默认粒子生命周期 2 秒 | | setParticleSize(sizeMeters) | 设置尾部轨迹粒子大小(米),运行中立即生效,控制台也可滑动调节 | | setParticleLife(seconds) | 设置尾部轨迹粒子生命周期(秒),运行中立即生效,控制台也可滑动调节 | | setParticleBackOffset(meters) | 设置粒子发射器相对路径运动点的前后偏移(米),正数向运动点后方,负数向运动点前方,0 表示运动点位置;运行中立即生效,控制台也可滑动调节 | | setParticleSideOffset(meters) | 设置粒子发射器相对路径运动点的左右偏移(米),正数向运动点右侧,负数向运动点左侧,0 表示运动点位置;运行中立即生效,控制台也可滑动调节 | | setGlowEnabled(enabled, config?) | 开启/关闭呼吸闪烁辉光粒子,默认绿色,最高透明度 80%,支持 CSS 颜色或配置对象 | | setGlowSize(sizeMeters) | 设置辉光粒子大小(米),控制台也可滑动调节 | | setLoop(enabled) | 开启/关闭循环播放 | | setReturnMotion(enabled) | 开启/关闭折返运动,反向段会在模型基础朝向上叠加 180° | | setTrajectoryVisible(visible) | 显示/隐藏运动轨迹线 | | setPathEditorEnabled(enabled) | 开启/关闭地图路径编辑,开启后左键点击地图创建点位 | | setPathDraft(presetOrPoints) | 设置当前路径草稿,支持完整 JSON 或点位数组 | | closePathLoop() | 首尾相连:记录 closedLoop 标识,按当前轨迹模式连接两端;直线模式补直线闭合段,平滑模式按闭合曲线处理 | | saveCurrentPath(name) | 保存当前路径到 localStorage | | loadPathPreset(id) | 从 localStorage 读取路径并运行中切换 | | exportCurrentPath() | 导出当前路径 JSON 字符串 | | importPathPreset(json) | 导入路径 JSON 并应用到当前动画 | | destroy() | 销毁,移除所有监听与场景对象 |

路径点格式

{ lon: 经度, lat: 纬度, height: 高度(米) }

路径 JSON 格式

{
  "id": "path-1710000000000",
  "name": "演示路径",
  "version": 1,
  "mode": "bezier",
  "speed": 120,
  "closedLoop": false,
  "points": [
    { "lon": 116.39, "lat": 39.9, "height": 300 },
    { "lon": 116.41, "lat": 39.91, "height": 600 }
  ],
  "createdAt": 1710000000000,
  "updatedAt": 1710000000000
}

路径控制台支持读取 localStorage 中的路径列表,运行中可通过下拉框切换;“新建路径”会创建一条空草稿,第一次点击“保存路径”会弹出控制台风格的名称表单,已保存过的路径再次点击“保存路径”会把当前最新数据覆盖保存到本地,“另存为新路径”始终会弹出名称表单并生成一条新路径。“导出 JSON”会直接下载当前路径 JSON 文件;路径管理器下方的 JSON 输入框始终显示当前路径 JSON,地图点位变化会实时更新该输入框,直接修改输入框里的 JSON 也会实时同步到地图点位。“首尾相连”会把当前路径标记为 closedLoop: true,不再依赖末尾重复首点;直线轨迹会补上尾点到首点的直线闭合段,平滑轨迹会按闭合曲线处理两端切线。编辑模式开启后会自动进入自由镜头,地图可直接左键拖动观察;界面底部会显示半透明操作提示:单击空白区域可添加路径点,右键路径线段可在该位置插入路径点,右键路径点会弹出删除按钮;左键拖动已有路径点或三向轴可调整位置,拖动期间编辑器会临时接管鼠标,松手后恢复地图拖动。

控制台主面板保留播放、视角、相机距离、相机环绕角度、相机俯仰等常用控制;顶部“当前编辑对象”下拉默认以“动画对象 1 / 2 ...”区分多个插件实例,外部传入 console.label 时优先使用自定义名称;下拉框下方提供“本地上传模型”入口,选择 .glb / .gltf 后会立即使用本地模型。多个插件实例会各自维护模型、路径、粒子、辉光和轨迹状态;共享控制台只负责切换当前编辑对象,本地路径列表仍是全局可选列表。

控制台把“当前编辑对象”和“相机跟随对象”分开管理:当前编辑对象决定模型初始化、路径管理、粒子、辉光、轨迹线等设置作用到谁;相机跟随对象决定场景相机现在看谁。多个模型可以同时移动,但相机同一时间只跟随一个对象;选择“自由镜头 / 不跟随”会交还 Cesium 默认相机控制。插件以宿主 viewer.clock.currentTime 作为时间源,不接管宿主倍率;每个插件实例独立维护播放开关和播放速度。宿主 clock 正在推进时,只有插件自身处于播放状态的对象才会运动;宿主 clock 没有推进时,插件播放会临时启动 clock 作为时间源,最后一个由插件启动的动画暂停或销毁后会释放该临时状态。

“路径管理器”位于相机控制下方;“首尾相连”会把当前路径标记为 closedLoop: true,不再依赖末尾重复首点;直线轨迹会补上尾点到首点的直线闭合段,平滑轨迹会按闭合曲线处理两端切线。点位较多时,闭合曲线采样会自动分帧处理,避免点击瞬间阻塞页面。粒子颜色、轨迹粒子大小、粒子生命周期、粒子前后偏移、粒子左右偏移、辉光颜色、辉光大小已收纳到“粒子管理”;粒子跟随路径运动点,不继承模型自身坐标轴、缩放或内置动画偏移。模型初始缩放、模型亮度倍数、初始朝向、初始俯仰已收纳到“模型初始化”。模型缩放有效范围为 0.00110000,无历史初始化设置的新模型默认使用 20 倍;模型亮度有效范围为 0.110,默认 1 倍;底层 Cesium 环境光照因子会自动限制在 01,因此高于 1 的亮度值只作为插件侧初始化参数保存,不会直接写入 Cesium 的受限字段。控制台缩放滑块使用换算映射,能同时兼顾极小值和大值调节。模型初始化设置会按模型名保存到 localStorage,同一个模型下次加载时会自动恢复缩放、亮度、朝向、俯仰和滚转;本地上传模型按文件名记忆这些初始化参数,但模型文件本体不会写入 localStorage。

模型初始化本地存储 key 为 cesium-path-animation:model-settings:v1,结构按模型名索引:

{
  "plane.glb": {
    "version": 1,
    "modelName": "plane.glb",
    "url": "/model/plane.glb",
    "scale": 20,
    "brightness": 1,
    "heading": 1.5708,
    "pitch": 0,
    "roll": 0,
    "updatedAt": 1710000000000
  }
}

跟随外部 Cesium 对象

默认情况下,相机会跟随 CesiumPathAnimation 内部创建的模型。如果你的模型已经由业务系统自己绘制,也可以把外部对象作为 followTarget 传进来。此时插件只负责相机跟随、路径控制台、粒子、辉光等能力,不强制接管你的模型绘制方式。

followTarget 的核心不是“模型必须是什么类”,而是“每一帧能不能拿到目标当前位置”。因此除了直接传 EntityCesium.ModelModelInstanceCollection 实例信息,也可以传一个位置解析函数。位置解析函数就是业务系统提供给插件的取位置接口:插件每帧把当前时间和一个可复用的 result 传进去,函数返回目标当前的 Cartesian3。这种方式最适合业务侧自己维护模型池、合批模型、拾取 ID、矩阵缓存的场景。

位置解析函数格式:

(time, result) => Cesium.Cartesian3 | undefined
  • time:当前 Cesium 时间,适合读取动态位置。
  • result:插件提供的复用对象,建议把结果写进去再返回,减少每帧创建新对象。
  • 返回值:目标当前世界坐标;返回 undefined 时,本帧不会更新到无效位置。

1. 跟随 Entity 模型

const entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(110.35, 20.01, 500),
  model: { uri: '/model/drone.glb', scale: 10 }
})

const anim = new CesiumPathAnimation({
  viewer,
  followTarget: entity,
  camera: {
    mode: CAMERA_MODE.FIXED,
    distance: 3000,
    angle: { heading: 0, pitch: Cesium.Math.toRadians(-30) }
  }
})

// 后续也可以动态切换跟随目标
anim.setFollowTarget(entity)

2. 跟随 Cesium.Model 单模型

const model = await Cesium.Model.fromGltfAsync({
  url: '/model/drone.glb',
  modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(110.35, 20.01, 500)
  ),
  scale: 10
})
viewer.scene.primitives.add(model)

const anim = new CesiumPathAnimation({
  viewer,
  followTarget: model,
  camera: {
    mode: CAMERA_MODE.THIRD_PERSON,
    distance: 3000
  }
})

如果你使用的是旧版同步创建方式,也可以这样传:

const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
  url: '/model/drone.glb',
  modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(110.35, 20.01, 500)
  ),
  scale: 10
}))

anim.setFollowTarget(model)

3. 跟随 ModelInstanceCollection 合批模型中的某个实例

如果宿主项目能直接拿到 ModelInstanceCollection 对象,并且能确定实例下标,可以直接传 { collection, index }

const collection = viewer.scene.primitives.add(new Cesium.ModelInstanceCollection({
  url: '/model/tree.glb',
  instances: [
    {
      modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
        Cesium.Cartesian3.fromDegrees(110.35, 20.01, 0)
      )
    },
    {
      modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
        Cesium.Cartesian3.fromDegrees(110.36, 20.02, 0)
      )
    }
  ]
}))

anim.setFollowTarget({
  collection,
  index: 1
})

但在真实业务里,普通合批模型通常由渲染器统一管理:渲染器保存业务 ID、实例顺序、矩阵缓存,并在 scene.pick 后把 picked.instanceId 转成业务 ID。此时更推荐把“业务 ID 到世界坐标”的位置解析函数传给插件,插件不需要知道你的合批集合内部怎么维护:

const pickedInfo = modelRenderer.resolvePickObject(picked)

if (pickedInfo?.source === 'model-instance') {
  anim.setFollowTarget((time, result) => {
    const position = modelRenderer.getItemWorldPosition(pickedInfo.id)
    return position ? Cesium.Cartesian3.clone(position, result) : undefined
  })
}

这种方式适合:

  • 普通合批模型:ModelInstanceCollection
  • 业务模型池:同一个模型资源复用给很多目标
  • 拾取后只有业务 ID,没有直接暴露 Cesium 实例
  • 模型矩阵由业务系统持续更新

4. 自定义跟随位置函数

如果你的外部对象不是以上三种结构,只要能返回 Cartesian3,也可以直接传函数。建议优先把坐标写入 result 后返回:

const anim = new CesiumPathAnimation({
  viewer,
  followTarget: (time, result) => {
    return Cesium.Cartesian3.fromDegrees(110.35, 20.01, 500, undefined, result)
  },
  camera: { mode: CAMERA_MODE.FIXED, distance: 3000 }
})

多对象同时移动

每创建一个 CesiumPathAnimation,就代表一个独立的动画对象。一个对象包含一个模型、一条当前轨迹、一套粒子/辉光/轨迹线状态。多个对象共用宿主 viewer.clock.currentTime 作为时间源,但播放开关和播放速度由各自实例独立维护;宿主 clock 正在推进时只有调用过 play() 的对象会移动,宿主 clock 没有推进时插件会在播放期间临时启动时间源。

const droneA = new CesiumPathAnimation({
  viewer,
  console: { label: '无人机 A' }
})
droneA.setModel('/model/drone-a.glb', { scale: 20 })
droneA.setPath({
  name: '巡检路线 A',
  speed: 120,
  points: [
    { lon: 110.303, lat: 20.03, height: 500 },
    { lon: 110.354, lat: 20.035, height: 800 }
  ]
})

const droneB = new CesiumPathAnimation({
  viewer,
  console: { label: '无人机 B' }
})
droneB.setModel('/model/drone-b.glb', { scale: 20 })
droneB.setPath({
  name: '巡检路线 B',
  speed: 90,
  points: [
    { lon: 110.285, lat: 19.985, height: 400 },
    { lon: 110.412, lat: 20.002, height: 700 }
  ]
})

droneA.play()

控制台里可以分别选择“当前编辑对象”和“相机跟随对象”:编辑对象用于改模型、路径、粒子和轨迹线;跟随对象用于决定相机看谁。

相机交互

  • 随目标固定视角(FIXED):默认相机模式,默认相机距离 5000 米;普通观察时直接按住鼠标左键拖拽,修改相机围绕目标的环绕角度和俯仰角度;开启轨迹点编辑后会自动进入自由镜头,可直接拖动地图观察。
  • 定点固定视角:控制台点击“定点固定视角”后,会弹出与控制台同风格的经纬高表单;确认后相机会切到固定视角并围绕该坐标点观察;点击“恢复随目标固定”可恢复围绕模型当前位置。
  • 第三人称跟随(THIRD_PERSON):普通观察时直接按住鼠标左键拖拽,可在跟随运动方向的基础上调整环绕偏移和俯仰角度;开启轨迹点编辑后会自动进入自由镜头,可直接拖动地图观察。
  • 自动环绕:默认开启,默认速度 2°/s;控制台开启“自动环绕”后,仅在随目标固定视角生效;用户 1 秒无鼠标操作时,相机会从静止慢慢加速到设定环绕速度,速度可在控制台调节。
  • 第三人称跟随(THIRD_PERSON)与固定视角跟随:鼠标滚轮控制与目标的距离,按当前视线角度斜率缩放;固定模式最大相机距离 500 万米。
  • 自由镜头(FREE):交还 Cesium 默认相机控制,操作方式保持 Cesium 原样。

运行示例

npm run demo
# 或只启动 demo 目录
npm run demo:package

发布包会包含 srcdemoREADME.md;因此安装包里也会带上海口双对象 demo 与默认模型 demo/demo.gltf