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

map-cesium-utils

v1.0.0

Published

cesium utils library

Readme

map-cesium-utils

基于 CesiumJS 的实例化地图与空间业务库。每次 createMap() 都创建独立的 Viewer、运行时、图层、要素、交互和资源生命周期,可在同一页面安全运行多个地图实例。

旧的全局 createViewer()createLayer()startDraw()createPlayback() 等 API 已删除,不提供弃用别名。

安装

pnpm add map-cesium-utils cesium

cesium可选 peer dependency,由宿主项目安装。使用 createMap()、包根其余能力或 map-cesium-utils/interop 时必须安装;只使用 map-cesium-utils/spatial(纯领域的坐标、路径、区域、分析与校验能力)时可以不装 Cesium:

pnpm add map-cesium-utils

快速开始

import { DrawGeometryType, createMap } from 'map-cesium-utils'

const map = createMap('cesium-container', {
  viewerOptions: { baseLayer: false }
})

const business = map.createLayer('business')
const [entity] = business.add([
  {
    _uuid: 'station-1',
    geometry: { type: 'Point', coordinates: [120.15, 30.28] }
  }
])

const drawing = await business.draw(DrawGeometryType.Polygon)
map.feature.updateStyle(entity, { strokeColor: '#ff7a00' })
await business.flyTo()

drawing.cancel()
await map.destroy()

map.viewer 是 Cesium 原生互操作出口,但 Viewer 生命周期仍由当前 Map 管理;调用方不要直接执行 viewer.destroy()

map.pointer.pickObject()onObjectClick() / onObjectHover() 会把场景命中归一化为 entitypoint-primitive3d-tiles-feature,同时继续复用当前 Map 的输入路由:

const stop = map.pointer.onObjectClick({
  onHit: ({ result }) => {
    if (result.kind === '3d-tiles-feature') {
      console.log(result.object.getPropertyIds())
    }
  }
})

stop()

矩形框选使用 Cesium 原生区域拾取,结果可直接交给现有 Selection:

map.pointer
  .pickAllInRectangle({ start, end }, map.feature.isManaged)
  .forEach((entity) => map.selection.select(entity, { additive: true }))

实例 API

| 入口 | 能力 | | --- | --- | | map.createLayer() / getLayer() / listLayers() | 稳定名称图层与 MapLayer 句柄 | | map.feature / map.selection | 要素增删改查、样式、选择和移动 | | map.pointer | 位置、Entity、PointPrimitive 与 3D Tiles 要素拾取及监听 | | map.draw / map.edit / map.measure | 互斥的绘制、单/多要素编辑和量测会话 | | map.scene | 相机、地形、影像、3D Tiles、高度、海量点与原生聚合图层 | | map.motion | 回放、动态对象和相机跟踪 | | map.interop | GeoJSON、KML/KMZ、WKT 导入导出及 KML/CZML 原生资源 | | map.spatial | 路径编辑和区域运行时 | | map.onStateChange() / destroy() | 实例状态与幂等清理 |

完整方法、参数和返回类型以发布包的 dist/index.d.mts / dist/index.d.cts 为准;公开值导出由 test/index.test.ts 固定。

图层句柄(MapLayer)

createLayer(name) 是同步、幂等的 get-or-create 操作,返回绑定稳定名称的 MapLayer

const layer = map.createLayer('business', { autoHover: true })

layer.add(data, style)
layer.append(moreData)
layer.style(patch)
await layer.draw(DrawGeometryType.LineString)
layer.importGeoJson(input)
await layer.flyTo()
layer.removeLayer()

等待 Cesium DataSource 实际挂载时使用 await layer.ready()

MapLayer 只在其名称仍绑定创建时的 DataSource 期间有效。删除图层或用同名图层替换后,旧句柄的后续操作会抛出“已失效”;正在等待的 ready()flyTo()、绘制会话及 GeoJSON/KML/KMZ 异步导入也会随图层删除而失败、取消或中止,避免结果写入后来创建的同名图层。

removeRawEntity(entity) 只删除当前图层拥有的 Entity;由要素模块管理的 Entity 会经过统一要素生命周期清理,其他图层的 Entity 返回 false

会话句柄

绘制、编辑、量测和路径编辑的 start() 返回本次会话的句柄。保存句柄后调用 finish()cancel()undo()redo();句柄不会误操作后来替换它的新会话。

const edit = await map.edit.start(entity)

edit.undo()
edit.redo()
edit.finish()

const group = await map.edit.startMany([first, second])
group.translate({ longitude: 0.01, latitude: -0.02 })
group.undo()
group.finish()

这些能力共用 primary-canvas 互斥组,新会话会先清理同组旧会话。

资源句柄

场景和运动资源使用绑定创建记录的句柄:

const imagery = map.scene.imagery.add('base', imageryLayer)
imagery.setOpacity(0.8)

const clustered = await map.scene.clusterLayers.add('stations', points)
const flight = await map.interop.czml.load('flight', czml)

const playback = map.motion.playback.create('flight', source)
await playback.play()
await playback.remove()

删除并重建同名资源后,旧句柄会失效,不会操作替代对象。

原生 KML/KMZ 资源可直接导出当前 Entity 集合,保留 Cesium 导出器支持的几何、高度、样式和时间信息:

const resource = await map.interop.kml.load('survey', kmlBlob)
resource.dataSource.entities.getById('route')!.name = '修改后的路线'
const { kml, externalFiles } = await resource.export()
const kmz = await resource.exportKmz()

export() 返回 KML 文本和外部资源文件;需要单文件交付时使用 exportKmz()。两者接受 Cesium 的 timemodelCallback 等导出选项及 signal,资源删除、同名重建或 Map 销毁会中止待处理导出。originalInput 始终是加载时的输入,不随 Entity 编辑同步。

删除图层或 Tileset、销毁 Map 时会取消所属的相机飞行;飞行 Promise 返回 false,不会继续占用新资源的相机状态。

地形通视分析复用可取消的地形剖面采样,并显式区分可见、遮挡和采样未解析:

const result = await map.scene.heights.analyzeLineOfSight(observer, target, {
  spacingMeters: 30
})

if (result.status === 'blocked') {
  console.log(result.firstObstruction)
}

轻量子路径

只使用无 Viewer 的纯函数时可从子路径导入:

import { parseWktGeometry } from 'map-cesium-utils/interop'
import { calculatePathStatistics } from 'map-cesium-utils/spatial'
  • map-cesium-utils/spatial:坐标、路径、区域、分析、校验和量测。
  • map-cesium-utils/interop:GeoJSON 与 WKT 纯函数。
  • 实例运行时始终从包根导入 createMap

大 GeoJSON 导入与取消

const controller = new AbortController()
const layer = map.createLayer('imported')
const importing = layer.importGeoJsonAsync(featureCollection, {
  batchSize: 500,
  timeBudgetMs: 8,
  signal: controller.signal,
  onProgress: ({ processed, total }) => console.log(processed, total)
})

// 用户取消或路由切换时调用;取消后本批次已创建的 Entity 会回滚。
controller.abort()
await importing.catch((error) => {
  if (error.name !== 'AbortError') throw error
})

异步处理按输入要素分批校验和展开,避免先同步校验整个 FeatureCollection;onProgress 报告 Entity 创建进度。timeBudgetMs 是创建阶段批次之间的让出目标,不是硬时间上限。文本的 JSON.parse、单个复杂几何处理和最终 UUID 去重仍同步执行;十万级数据应先测量主线程长任务和内存,再决定是否使用 Worker。

三维 WKT 编解码

import { geometryToWkt, parseWktGeometry } from 'map-cesium-utils/interop'

const geometry = parseWktGeometry('LINESTRING Z (120 30 100, 121 31 200)')
const text = geometryToWkt(geometry)

纯函数支持七类二维几何及 Point ZLineString Z,第三维原样保留,不执行高度基准转换。三维点和线导出时显式写入 Z;不支持隐式三维 WKT、M/ZM、三维 Polygon、Multi 或 GeometryCollection。map.interop.wkt.import() 仍遵守业务图形的二维约束,拒绝三维输入,避免静默丢失高度。

数据约定

  • 二维坐标为 [longitude, latitude],单位为度。
  • 支持 Point、LineString、Polygon、Rectangle、Circle。
  • Rectangle 使用 GeoJSON Polygon;Circle 使用圆心 Point,并通过 shapeType、半径和控制点恢复语义。
  • Polygon 保留外环和内洞;绘制和编辑默认阻止增加自相交。
  • 未解析高度不会冒充椭球高度;不同高度基准不会直接比较。
  • Cesium Entity 依赖对象身份;Vue 中保存 Entity 时使用 shallowRef
  • 拾取回调收到的 Cartesian2 是本次事件的独立快照,可以安全保存;Cesium 原生 ScreenSpaceEventHandler 的复用对象不会外泄。
  • 自行注册到 dataSource.entities.collectionChanged 的监听器必须自己 try/catch:Cesium 的 EntityCollection 在监听器抛出后会永久停止派发变更事件。

生命周期

每个 Map 独占 Viewer、MapRuntime、业务状态和画布输入。销毁顺序为:取消异步任务、释放交互和租约、释放其余资源、销毁 Viewer。

await map.destroy()

destroy() 幂等。单个清理失败不会阻断后续资源释放;多个错误通过 AggregateError 报告。销毁后所有实例命令都会拒绝继续工作。

销毁默认没有总时长上界(逐项清理各有 cleanupTimeoutMs 上限)。需要可预期的上界时传入总预算:

await map.destroy({ timeoutMs: 3000 })

预算耗尽后,剩余清理的同步部分仍会执行(解绑句柄、移除监听不会被跳过),只是不再等待其异步收尾,未完成项通过错误报告出来。

项目结构

src/
├── api/                  # createMap、CesiumMap、公共契约与组合根
├── runtime/              # 生命周期、任务、事件和交互租约
├── modules/              # Scene、Layer、Feature、Interaction、Motion、Interop、Spatial
├── platform/cesium/      # Viewer、Graphics、Picking 与交互适配
├── shared/               # 跨模块契约和无状态 Cesium 工具
├── entries/              # spatial、interop 子路径
└── index.ts              # 包根公共入口

模块边界、所有权和销毁顺序见 ARCHITECTURE.md,开发约束见 AGENTS.md

开发验证

从仓库根目录运行:

pnpm --dir packages/map-cesium check:types
pnpm --dir packages/map-cesium test   # 已串 check:types 与 check:boundaries
pnpm --dir packages/map-cesium check:boundaries   # 分层与依赖方向门禁
pnpm lint:check                       # 仓库统一的只读 lint
pnpm --dir packages/map-cesium build
pnpm --dir packages/map-cesium check:size
pnpm --dir packages/map-cesium check:package
pnpm --dir packages/map-cesium benchmark:check
pnpm --dir packages/example build

涉及 WebGL、鼠标或视觉行为时,还需在示例应用中做真实浏览器验收。

当前未承诺能力

  • KML <ExtendedData> 完全无损往返。
  • 任意原生 KML 文档的完全无损往返:资源句柄导出当前 Entity,但不保证恢复原 XML 结构、未被 Cesium 支持的扩展、NetworkLink 配置或任意 ExtendedData。

需要保留 Cesium 支持的 KML/KMZ 样式、时间、模型、路径与网络链接运行时语义时,使用 map.interop.kml.load(name, input);返回的句柄可控制显隐、移除资源,并通过 originalInput 取回未转换的原始字符串、Blob、Document 或 Resource。