关于 cesiumjs-core-utilities
面向 CesiumJS 开发者的核心工具与网络 API 指南,介绍 HTTP 资源、事件、请求调度、错误、工作线程、地图图钉及相关辅助工具。
主要功能
- 01获取数据并配置 HTTP 资源
- 02管理事件与请求限制
- 03处理错误和后台任务
- 04创建图钉并使用辅助工具
适用场景
- 01通过 Resource 获取 JSON 或上传数据
- 02调整瓦片加载的并发请求数
- 03管理事件监听器和工作线程任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cesiumgs/ cesiumjs-skills --skill cesiumjs-core-utilities安装后在 Claude Code 中输入/cesiumjs-core-utilities确认已加载。
详细介绍
CesiumJS 核心实用工具与网络
基线版本:CesiumJS v1.144+(ES 模块导入,defaultValue 已在 v1.134 中移除)
重大变更:移除 defaultValue(v1.134)
// WRONG (removed in v1.134)
const name = defaultValue(options.name, "default");
const opts = defaultValue(options, defaultValue.EMPTY_OBJECT);
// CORRECT (v1.134+)
import { Frozen } from "cesium";
const name = options.name ?? "default";
const opts = options ?? Frozen.EMPTY_OBJECT;
Frozen.EMPTY_OBJECT 是 Object.freeze({}),而 Frozen.EMPTY_ARRAY 是 Object.freeze([])。将它们用作选项对象和数组参数的安全默认值。
Resource:HTTP 请求与数据获取
Resource 是用于所有 HTTP 操作的统一类。它封装了 URL 构建、查询参数、标头、代理和重试逻辑。
获取数据
import { Resource } from "cesium";
// Static shorthand: accepts a URL string or options object
const jsonData = await Resource.fetchJson({ url: "https://api.example.com/data.json" });
// data: URIs work with Resource.fetchJson -- useful for inline GeoJSON or test fixtures
const dataUrl = "data:application/json," + encodeURIComponent(JSON.stringify(geojson));
const parsed = await Resource.fetchJson({ url: dataUrl });
// Instance-based: construct once, reuse for multiple fetches
const resource = new Resource({
url: "https://api.example.com/features",
queryParameters: { format: "json", limit: "100" },
headers: { "Authorization": "Bearer my-token" },
});
const features = await resource.fetchJson();
const text = await resource.fetchText(); // string
const buffer = await resource.fetchArrayBuffer(); // ArrayBuffer
const blob = await resource.fetchBlob(); // Blob
const image = await resource.fetchImage(); // HTMLImageElement or ImageBitmap
派生资源与模板值
import { Resource } from "cesium";
const api = new Resource({
url: "https://tiles.example.com/{version}/tiles/{z}/{x}/{y}.png",
templateValues: { version: "v2" },
headers: { "X-Api-Key": "abc123" },
});
// getDerivedResource inherits headers, proxy, and retry settings
const tile = api.getDerivedResource({
templateValues: { z: "10", x: "512", y: "384" },
});
const tileImage = await tile.fetchImage();
// Modify query parameters on an existing resource
resource.setQueryParameters({ access_token: "<access-token>" });
resource.appendQueryParameters({ extra: "param" });
重试与代理
import { Resource, DefaultProxy } from "cesium";
// Retry on specific HTTP status codes
const resource = new Resource({
url: "https://api.example.com/unstable",
retryAttempts: 3,
retryCallback: (resource, error) => {
if (error.statusCode === 429) {
return new Promise((resolve) => setTimeout(() => resolve(true), 2000));
}
return false;
},
});
// DefaultProxy appends the target URL as a query parameter
const proxied = new Resource({
url: "https://external-server.com/data.json",
proxy: new DefaultProxy("/proxy/"),
});
// Request goes to: /proxy/?https%3A%2F%2Fexternal-server.com%2Fdata.json
POST 与 PUT
import { Resource } from "cesium";
const resource = new Resource({ url: "https://api.example.com/upload" });
const result = await resource.post(JSON.stringify({ name: "test" }), {
headers: { "Content-Type": "application/json" },
});
// resource.put() works the same way
Color
RGBA 分量使用 [0.0, 1.0] 范围内的浮点数。包含 140 多个命名常量,作为冻结的静态属性,涵盖标准 CSS 颜色名称,采用 PascalCase 命名(例如,Color.RED、Color.ORANGE、Color.YELLOW、Color.GREEN、Color.BLUE、Color.CORNFLOWERBLUE、Color.ROYALBLUE、Color.FORESTGREEN、Color.CRIMSON、Color.TRANSPARENT)。
图钉的视觉评估构图
使用 PinBuilder 进行视觉评估时,图钉必须在截图中清晰可见。城市尺度的评审请使用 56-72 px 的图钉,设置 VerticalOrigin.BOTTOM,并使用 Rectangle.fromDegrees(...) 或合适的高度构图,确保所有图钉都能轻松显示在视口内。如果有一个图钉位于边缘,请缩小或重新居中;即使所有实体都存在,三枚图钉中只看到两枚也属于视觉评估失败。
创建颜色
import { Color } from "cesium";
const red = Color.RED; // frozen constant
const orange = Color.ORANGE; // frozen constant
const royalBlue = Color.ROYALBLUE; // frozen constant
const forestGreen = Color.FORESTGREEN; // frozen constant
const crimson = Color.CRIMSON; // frozen constant
const custom = new Color(0.2, 0.6, 0.8, 1.0); // float constructor
const blue = Color.fromCssColorString("#3498db"); // hex string
const semiRed = Color.fromCssColorString("rgba(255,0,0,0.5)"); // CSS rgba()
const coral = Color.fromBytes(255, 127, 80, 255); // 0-255 bytes
const hsl = Color.fromHsl(0.58, 0.8, 0.5, 1.0); // hue/sat/light
const bright = Color.fromRandom({ // constrained random
minimumRed: 0.75, minimumGreen: 0.75, minimumBlue: 0.75, alpha: 1.0,
});
操作与转换
import { Color } from "cesium";
const base = Color.fromCssColorString("#3498db");
const translucent = base.withAlpha(0.5); // new Color with alpha
const lighter = base.brighten(0.3, new Color()); // requires result param
const darker = base.darken(0.3, new Color());
const css = base.toCssColorString(); // "rgb(52,152,219)"
const hex = base.toCssHexString(); // "#3498db"
const bytes = base.toBytes(); // [52, 152, 219, 255]
const equal = Color.RED.equals(new Color(1.0, 0.0, 0.0, 1.0)); // true
事件系统
Event 是 CesiumJS 各处使用的发布-订阅机制。类会公开 Event 属性,例如 Viewer.selectedEntityChanged 和 Cesium3DTileset.tileLoad。
基本用法
import { Event } from "cesium";
const onDataReceived = new Event();
// addEventListener returns a removal function
const removeListener = onDataReceived.addEventListener((data) => {
console.log("Received:", data);
});
onDataReceived.raiseEvent({ id: 1, value: "test" }); // invoke all listeners
removeListener(); // unsubscribe
使用 EventHelper 批量清理
import { EventHelper } from "cesium";
const helper = new EventHelper();
helper.add(viewer.selectedEntityChanged, (entity) => {
console.log("Selected:", entity?.name);
});
// clock.onTick fires every animation frame; enable the clock with shouldAnimate
viewer.clock.shouldAnimate = true;
helper.add(viewer.clock.onTick, (clock) => { /* per-frame logic */ });
helper.add(viewer.scene.globe.tileLoadProgressEvent, (queueLength) => {
console.log("Tiles loading:", queueLength);
});
// Remove all listeners at once (e.g., in a destroy method)
helper.removeAll();
通过时钟滴答实时更新标签:
import { EventHelper, Color, Cartesian3 } from "cesium";
let tickCount = 0;
const label = viewer.entities.add({
position: Cartesian3.fromDegrees(-30.0, 30.0),
label: {
text: "Ticks: 0",
showBackground: true,
backgroundColor: Color.BLACK.withAlpha(0.7),
fillColor: Color.WHITE,
font: "24px monospace",
},
});
const helper = new EventHelper();
viewer.clock.shouldAnimate = true;
helper.add(viewer.clock.onTick, () => {
tickCount++;
label.label.text = "Ticks: " + tickCount;
});
RequestScheduler 配置
RequestScheduler 是一个用于管理并发请求限制的单例。Request 对象表示具有优先级和节流设置的独立 HTTP 请求(主要供内部使用)。
import { RequestScheduler } from "cesium";
RequestScheduler.maximumRequests = 64; // global max (default: 50)
RequestScheduler.maximumRequestsPerServer = 12; // per-server max (default: 18)
// Override for known HTTP/2 servers
RequestScheduler.requestsByServer = {
"api.cesium.com:443": 32,
"assets.cesium.com:443": 32,
};
错误处理
- DeveloperError —— 调用代码中的错误(参数无效)。仅在调试版本中抛出;请修复代码,不要捕获。
- RuntimeError —— 运行时故障(网络、着色器编译)。在生产环境中捕获。
import { RuntimeError, formatError, Cesium3DTileset } from "cesium";
try {
const tileset = await Cesium3DTileset.fromUrl("https://example.com/tileset.json");
viewer.scene.primitives.add(tileset);
} catch (error) {
if (error instanceof RuntimeError) {
console.error("Failed to load tileset:", error.message);
} else {
console.error(formatError(error)); // extracts name, message, stack
}
}
辅助函数
defined、clone、combine
import { defined, clone, combine } from "cesium";
// defined: returns true if value is neither null nor undefined
if (defined(entity.billboard)) {
entity.billboard.scale = 2.0;
}
// clone: shallow by default, pass true for deep
const obj = clone({ a: 1, nested: { b: 2 } }, true);
// combine: merge objects, first arg's keys take precedence
const merged = combine({ size: 20 }, { size: 10, color: "red" });
// { size: 20, color: "red" }
createGuid、buildModuleUrl
import { createGuid, buildModuleUrl } from "cesium";
const id = createGuid(); // "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
// Resolve paths relative to Cesium installation
const iconUrl = buildModuleUrl("Assets/Textures/maki/marker.png");
URL 实用工具
import { objectToQuery, queryToObject, getExtensionFromUri, getBaseUri } from "cesium";
const qs = objectToQuery({ key1: "value 1", key2: ["x", "y"] });
// "key1=value%201&key2=x&key2=y"
const parsed = queryToObject("key1=value%201&key2=x&key2=y");
// { key1: "value 1", key2: ["x", "y"] }
getExtensionFromUri("https://example.com/model.glb?v=2"); // "glb"
getBaseUri("https://example.com/data/model.glb"); // "https://example.com/data/"
destroyObject
将对象上的所有方法替换为会抛出 DeveloperError 的函数,并将 isDestroyed() 设置为返回 true。这是持有原生资源的对象的标准清理模式。
import { destroyObject } from "cesium";
class MyWidget {
constructor(viewer) {
this._handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
}
isDestroyed() { return false; }
destroy() {
this._handler.destroy();
return destroyObject(this);
}
}
AssociativeArray
提供 O(1) 键查找,并通过实时更新的 values 数组支持渲染循环中无需分配内存的迭代。
import { AssociativeArray } from "cesium";
const items = new AssociativeArray();
items.set("building-1", { height: 50 });
items.set("building-2", { height: 80 });
items.get("building-1"); // { height: 50 }
items.contains("building-1"); // true
// Iterate without per-frame allocations
const values = items.values;
for (let i = 0; i < values.length; i++) { /* process values[i] */ }
items.remove("building-1");
items.removeAll();
PinBuilder
生成地图图钉画布元素,可使用颜色、文本、maki 图标或自定义图像。
import { PinBuilder, Color, Cartesian3, VerticalOrigin } from "cesium";
const pin = new PinBuilder();
const redPin = pin.fromColor(Color.RED, 48); // solid color
const textPin = pin.fromText("A", Color.BLUE, 48); // text label
const iconPin = await pin.fromMakiIconId("hospital", Color.GREEN, 48); // maki icon
const urlPin = await pin.fromUrl("/icons/custom.png", Color.YELLOW, 48);
// Named color constants work directly -- any PascalCase CSS color name is valid
viewer.entities.add({
position: Cartesian3.fromDegrees(-75.17, 39.95),
billboard: {
image: pin.fromText("1", Color.ROYALBLUE, 48),
verticalOrigin: VerticalOrigin.BOTTOM,
},
});
viewer.entities.add({
position: Cartesian3.fromDegrees(-73.78, 40.64),
billboard: {
image: pin.fromText("2", Color.FORESTGREEN, 48),
verticalOrigin: VerticalOrigin.BOTTOM,
},
});
viewer.entities.add({
position: Cartesian3.fromDegrees(-118.41, 33.94),
billboard: {
image: pin.fromText("3", Color.CRIMSON, 48),
verticalOrigin: VerticalOrigin.BOTTOM,
},
});
DistanceDisplayCondition
根据相机距离控制实体、广告牌和标签的可见性。
import { DistanceDisplayCondition, Cartesian3, Color } from "cesium";
viewer.entities.add({
position: Cartesian3.fromDegrees(-75.17, 39.95),
billboard: {
image: "/icons/marker.png",
distanceDisplayCondition: new DistanceDisplayCondition(100.0, 50000.0),
},
});
功能检测与全屏
import { FeatureDetection, Fullscreen } from "cesium";
if (FeatureDetection.supportsWebAssembly()) { /* WASM workers OK */ }
if (FeatureDetection.supportsTypedArrays()) { /* TypedArrays OK */ }
if (Fullscreen.supportsFullscreen()) {
Fullscreen.requestFullscreen(viewer.container);
}
TaskProcessor
封装 Web Worker 以执行后台计算。Worker 会在首次调用 scheduleTask 时延迟创建。
import { TaskProcessor, defined } from "cesium";
const processor = new TaskProcessor("myWorkerModule");
const promise = processor.scheduleTask({ data: largeArray, op: "simplify" });
if (!defined(promise)) {
// Too many active tasks; retry next frame
} else {
const result = await promise;
}
processor.destroy(); // release worker when done
TrustedServers
仅向已注册的服务发送凭据(Cookie、身份验证标头)。
import { TrustedServers } from "cesium";
TrustedServers.add("secure-tiles.example.com", 443);
TrustedServers.contains("https://secure-tiles.example.com/tileset.json"); // true
TrustedServers.remove("secure-tiles.example.com", 443);
性能提示
- 重复使用 Resource 实例 ——
getDerivedResource会继承代理、请求头和重试配置,而无需重新解析 URL。 - 针对 HTTP/2 调整 RequestScheduler —— 通过
requestsByServer提高maximumRequests和每个服务器的请求限制,以加快瓦片加载速度。 - 使用
Frozen.EMPTY_OBJECT作为默认值 —— 避免在高频路径的每次调用中都分配一个新的{}。 - 优先使用
defined(),而非真值判断 —— 正确区分0、""和false与null/undefined。 - 在渲染循环中使用 AssociativeArray —— 其
values数组可避免每帧分配Object.keys()的结果。 - 谨慎设置 retryAttempts —— 通过
retryCallback针对特定状态码(401、429、503)限制重试。 - 完成后销毁 TaskProcessors —— 空闲的工作线程仍会占用内存。
- 切勿修改冻结的 Color 常量 —— 先调用
.clone()或.withAlpha()。 - 在 catch 代码块中使用
formatError—— 从任何类型的错误中提取名称、消息和堆栈。 - 缓存 PinBuilder 的输出 —— 在多帧中生成许多相同图钉时,保存 canvas 引用。
另请参阅
- cesiumjs-viewer-setup —— Viewer 初始化、Ion 令牌、场景配置
- cesiumjs-imagery —— 使用
Resource获取瓦片的影像提供程序 - cesiumjs-entities —— 使用
Color、DistanceDisplayCondition和PinBuilder的 Entity API