cesiumjs-entities について
cesiumjs-entitiesは、データ駆動型の地球シーンを構築するCesiumJS開発者向けスキルです。Entityのグラフィックス、コレクション、外部データソース、クラスタリング、表示制御を扱います。
主な機能
- 01点・線・面・モデルのEntityグラフィックス
- 02EntityCollectionの検索と削除
- 03GeoJSON、KML、CZML、GPXの読み込み
- 04Entityのクラスタリングと親子表示制御
活用シーン
- 01ラベル付き地点や3D形状の表示
- 02地理データファイルの読み込みとスタイル設定
- 03Entityグループとクラスタの管理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cesiumgs/ cesiumjs-skills --skill cesiumjs-entitiesインストール後、Claude Code で/cesiumjs-entitiesを入力して読み込まれたか確認します。
詳細
CesiumJS エンティティとデータソース
バージョンの基準: CesiumJS 1.144 -- ES モジュールのインポート:
import { ... } from "cesium";所有権のルール:*Graphicsクラスはここに属します。*Geometryクラスは cesiumjs-primitives に属します。プロパティ(SampledProperty、CallbackProperty、MaterialProperty のサブタイプ)は cesiumjs-time-properties に属します。
アーキテクチャ
Entity API は、CesiumJS の高レベルなデータ駆動型レイヤーです。エンティティは位置、向き、1 つ以上の Graphics タイプを単一のオブジェクトにまとめ、EntityCollection によって管理されます。DataSource は外部形式(GeoJSON、KML、CZML、GPX)を読み込み、EntityCollection にエンティティを自動的に追加します。Visualizer と GeometryUpdater は、各フレームで Entity の記述を Primitive に変換します。
DataSource --> EntityCollection --> Entity
|-- position / orientation
|-- billboard / point / label / model / polygon / polyline / ...
|-- properties (PropertyBag)
viewer.entitiesは、既定の DataSource の EntityCollection へのショートカットですviewer.dataSourcesは、読み込まれたすべての DataSource を保持します。それぞれが独自のEntityCollectionを所有します
座標とフレーミングのルール(最初にお読みください)
視覚評価で発生する失敗のほとんどは、API のエラーではなく、座標の符号やカメラのフレーミングの間違いです。以下のルールを必ず覚えておいてください。
-
西半球の経度は負の値です。 NYC =
-74.006、Los Angeles =-118.24、Chicago =-87.63、Denver =-104.99です。マイナス記号が抜けると、NYC はインド/パキスタン上に配置されます。送信する前に、西半球の座標には必ずマイナス記号があることを確認してください。 -
fromDegrees(longitude, latitude, height?)-- 経度が先で、次に緯度です。順序を取り違えるのが最もよくあるバグです。 -
エンティティを追加した後は、必ず表示範囲に収めてください。 カメラを既定の太平洋中心の表示のままにしないでください。次のいずれかを選びます。
viewer.zoomTo(target)-- target には Entity、Entity[]、EntityCollection、または DataSource を指定できます。データの読み込み後に解決されます。viewer.flyTo(target, { duration, offset })-- アニメーション付きです。完了するとtrueに解決される Promise を返します。await ...load(...)で読み込んだ DataSource には、viewer.zoomTo(ds)を呼び出してください(ds.entitiesではありません)。これにより、すべてのエンティティを対象にバウンディングスフィアが計算されます。
-
地域全体または地球全体にまたがるコレクションの場合(例:「米国本土」、「NYC/Paris/Sydney にある 3 つすべてのランドマーク」)、エンティティの 配列 または DataSource に対する
zoomTo/flyToを優先してください。対象をすべて含むバウンディングスフィアに自動的に合わせられます。手作業で指定するCartesian3の移動先やピッチ値では、反対側の半球を表示したり、データの半分が画面から切れたりすることがよくあります。const nyc = viewer.entities.add({ /* Statue of Liberty, -74.04, 40.69 */ }); const paris = viewer.entities.add({ /* Eiffel Tower, 2.29, 48.86 */ }); const sydney = viewer.entities.add({ /* Sydney Opera, 151.22, -33.86 */ }); await viewer.zoomTo([nyc, paris, sydney]); // single call, fits all three -
地球全体を表示するマーカーの視覚評価では、マーカーを大きくし、深度に依存しないようにしてください。
point.pixelSizeは 22~32 程度にし、黒または白のアウトライン、ラベルのオフセットを設定します。また、利用できる場合は point と label の両方にdisableDepthTestDistance: Number.POSITIVE_INFINITYを設定してください。 ラベルは見えていても、色付きの点が 2 つ見えない地球表示は、視覚評価では失敗です。 -
対象となるエンティティがない単一の AOI をフレーミングする場合は、
viewer.camera.flyTo({ destination: Rectangle.fromDegrees(west, south, east, north) })を優先してください。矩形に自動的に合わせられます。カメラを詳細に制御する方法については、cesiumjs-camera を参照してください。
Entity の基本
点
import { Viewer, Cartesian3, Color, HeightReference } from "cesium";
const viewer = new Viewer("cesiumContainer");
const entity = viewer.entities.add({
id: "my-point", // optional; auto-generated GUID if omitted
name: "Sample Point",
position: Cartesian3.fromDegrees(-75.59777, 40.03883),
point: {
pixelSize: 10,
color: Color.YELLOW,
outlineColor: Color.BLACK,
outlineWidth: 2,
heightReference: HeightReference.CLAMP_TO_GROUND,
},
});
viewer.zoomTo(entity);
ラベル付きビルボード
import { Viewer, Cartesian3, Cartesian2, Color, VerticalOrigin, HeightReference, LabelStyle } from "cesium";
const viewer = new Viewer("cesiumContainer");
viewer.entities.add({
position: Cartesian3.fromDegrees(-122.4175, 37.7749),
billboard: {
image: "/assets/marker.png",
scale: 0.5,
verticalOrigin: VerticalOrigin.BOTTOM,
heightReference: HeightReference.CLAMP_TO_GROUND,
},
label: {
text: "San Francisco",
font: "14px sans-serif",
fillColor: Color.WHITE,
outlineColor: Color.BLACK,
outlineWidth: 2,
style: LabelStyle.FILL_AND_OUTLINE,
pixelOffset: new Cartesian2(0, -36),
heightReference: HeightReference.CLAMP_TO_GROUND,
},
});
点とラベルは、通常 1 つのエンティティにまとめるほうがすっきりします。 同じ Entity に
point/billboardとlabelの両方を設定すると、完全に同じ位置に配置され、 選択対象の重複を避けられます。また、各地点に鮮明なラベルを 1 つ表示できます。 ラベルに独立した表示/非表示、親、または時間に応じた動作が必要な場合に限り、 別々のエンティティを使用してください。
ポリゴン(平面、押し出し、穴あり)
import { Viewer, Cartesian3, Color, PolygonHierarchy } from "cesium";
const viewer = new Viewer("cesiumContainer");
// Flat polygon
viewer.entities.add({
polygon: {
hierarchy: Cartesian3.fromDegreesArray([-115, 37, -115, 32, -107, 33, -102, 31, -102, 35]),
material: Color.RED.withAlpha(0.5),
outline: true,
outlineColor: Color.BLACK,
},
});
// Extruded polygon with hole
viewer.entities.add({
polygon: {
hierarchy: new PolygonHierarchy(
Cartesian3.fromDegreesArray([-99, 30, -85, 30, -85, 40, -99, 40]),
[new PolygonHierarchy(Cartesian3.fromDegreesArray([-97, 32, -87, 32, -87, 38, -97, 38]))]
),
extrudedHeight: 300000,
material: Color.BLUE.withAlpha(0.6),
closeTop: true,
closeBottom: true,
},
});
ポリライン
import { Viewer, Cartesian3, Color, ArcType } from "cesium";
const viewer = new Viewer("cesiumContainer");
viewer.entities.add({
polyline: {
positions: Cartesian3.fromDegreesArray([-75, 35, -125, 35]),
width: 5,
material: Color.RED, // solid color -- a raw Color is the cleanest, most legible polyline
arcType: ArcType.GEODESIC,
clampToGround: true,
},
});
ポリラインのマテリアルに関する注意点: ルートを「見た目にわかりやすく」表示するには、生の
Color(例:Color.RED)をmaterialに直接渡してください。Dash、Glow、Arrow の各マテリアルは テクスチャを加えるため、評価者が描画アーティファクトや色あせた線と誤認することがあります。 シナリオでスタイル付きの線が明示的に求められている場合にのみ使用してください。
3D モデル
import { Viewer, Cartesian3, HeadingPitchRoll, Transforms, Math as CesiumMath, Color } from "cesium";
const viewer = new Viewer("cesiumContainer");
const position = Cartesian3.fromDegrees(-123.075, 44.045, 5000);
const hpr = new HeadingPitchRoll(CesiumMath.toRadians(135), 0, 0);
viewer.entities.add({
position,
orientation: Transforms.headingPitchRollQuaternion(position, hpr),
model: {
uri: "/assets/CesiumAir/Cesium_Air.glb",
minimumPixelSize: 64,
maximumScale: 20000,
silhouetteColor: Color.RED,
silhouetteSize: 2,
},
});
ボックス、円柱、楕円体、楕円
import { Viewer, Cartesian3, Color } from "cesium";
const viewer = new Viewer("cesiumContainer");
viewer.entities.add({ // Box
position: Cartesian3.fromDegrees(-107, 40, 300000),
box: { dimensions: new Cartesian3(400000, 300000, 500000), material: Color.BLUE.withAlpha(0.5) },
});
viewer.entities.add({ // Cylinder (topRadius: 0 for a cone)
position: Cartesian3.fromDegrees(-100, 40, 200000),
cylinder: { length: 400000, topRadius: 200000, bottomRadius: 200000, material: Color.GREEN.withAlpha(0.5) },
});
viewer.entities.add({ // Ellipsoid (sphere when all radii equal)
position: Cartesian3.fromDegrees(-93, 40, 300000),
ellipsoid: { radii: new Cartesian3(200000, 200000, 300000), material: Color.RED.withAlpha(0.5) },
});
viewer.entities.add({ // Ellipse (circle when axes equal)
position: Cartesian3.fromDegrees(-86, 40),
ellipse: { semiMajorAxis: 300000, semiMinorAxis: 300000, material: Color.PURPLE.withAlpha(0.5) },
});
押し出しボリューム(ボックス/円柱/押し出しポリゴン)にもフレーミングが必要です。 シナリオで「コロラド上の押し出し柱」(経度約 -105、緯度約 39)が求められた場合は、エンティティを追加してから
viewer.zoomTo(entity)を呼び出してください。そうしないと、プログラム上のチェックがすべて合格していても、デフォルトのカメラがカナダや北部の平原を向き、柱がフレームから外れることがよくあります。
コリドー、長方形、ウォール
import { Viewer, Cartesian3, Color, Rectangle, CornerType } from "cesium";
const viewer = new Viewer("cesiumContainer");
viewer.entities.add({ // Corridor: path with width
corridor: { positions: Cartesian3.fromDegreesArray([-80, 40, -90, 40, -90, 35]), width: 200000, material: Color.ORANGE.withAlpha(0.6), cornerType: CornerType.ROUNDED },
});
viewer.entities.add({ // Rectangle by geographic bounds
rectangle: { coordinates: Rectangle.fromDegrees(-110, 20, -80, 25), material: Color.GREEN.withAlpha(0.5), extrudedHeight: 50000 },
});
viewer.entities.add({ // Wall: vertical curtain
wall: { positions: Cartesian3.fromDegreesArrayHeights([-115, 44, 200000, -90, 44, 200000]), minimumHeights: [100000, 100000], material: Color.CYAN.withAlpha(0.7) },
});
EntityCollection の操作
viewer.entities.getById("my-point"); // retrieve by ID
viewer.entities.getOrCreateEntity("some-id"); // get or create
viewer.entities.values; // Entity[] (read-only)
viewer.entities.remove(entity); // remove by reference
viewer.entities.removeById("my-point"); // remove by ID
viewer.entities.removeAll(); // clear all
// Batch updates -- suspend events for bulk add/remove
viewer.entities.suspendEvents();
for (let i = 0; i < 1000; i++) viewer.entities.add({ /* ... */ });
viewer.entities.resumeEvents(); // fires one collectionChanged event
viewer.entities.collectionChanged.addEventListener((collection, added, removed, changed) => {
console.log(`Added: ${added.length}, Removed: ${removed.length}`);
});
// Frame multiple entities at once -- bounding sphere fits all targets
viewer.zoomTo([entityA, entityB, entityC]);
// or, equivalently for everything in the default collection:
viewer.zoomTo(viewer.entities);
entity.show = falseにしても、エンティティはコレクションに残ります。entities.values.lengthのカウントには含まれますが、レンダリングとzoomToの境界球からは除外されます。完全に削除するにはremoveByIdを使用してください。一部のエンティティを「非表示」にし、ほかのエンティティを「削除」するよう求めるシナリオでは、この違いが重要です。非表示のエンティティはentity_countのチェックに含まれますが、削除されたエンティティは含まれません。
DataSources
GeoJSON/TopoJSON
import { Viewer, GeoJsonDataSource, Color } from "cesium";
const viewer = new Viewer("cesiumContainer");
// Load from URL with styling options
const ds = await GeoJsonDataSource.load("/data/counties.geojson", {
stroke: Color.HOTPINK, fill: Color.PINK.withAlpha(0.5), strokeWidth: 3, clampToGround: true,
});
viewer.dataSources.add(ds);
await viewer.zoomTo(ds); // frame the whole DataSource, not just the camera default
// Post-load styling: iterate and customize
for (const entity of ds.entities.values) {
if (entity.polygon) entity.polygon.material = Color.fromRandom({ alpha: 0.8 });
}
GeoJsonDataSource.load() は、URL の代わりにインラインの GeoJSON オブジェクトも受け付けます。
エンティティ、DataSource のライフサイクル、クラスタリング、時間によって動的に変化するプロパティ、または読み込み後にエンティティごとのスタイルを簡単に設定したい場合は、GeoJsonDataSource を使用してください。大規模な静的 GeoJSON でエンティティのオーバーヘッドがボトルネックになる場合は、代わりに cesiumjs-primitives スキルの GeoJsonPrimitive を使用してください(1.142 で追加)。
米国本土をフレーミングする際のヒント: 米国各州の GeoJSON を読み込んだ後に
viewer.zoomTo(ds)(完了を待機)を呼び出すと、下位48州全体の境界球に合わせて表示できます。手動で調整したカメラの高さ(例:z ≈ 7M)では、北部の州(WA/MT/ME)や南端(FL)が切れたり、ズームしすぎて海岸線が切れたりすることがよくあります。DataSource の境界球に任せてください。
KML/KMZ
import { KmlDataSource } from "cesium";
const ds = await KmlDataSource.load("/data/sample.kml", {
camera: viewer.scene.camera, canvas: viewer.scene.canvas, clampToGround: true,
});
viewer.dataSources.add(ds);
viewer.flyTo(ds);
CZML
import { CzmlDataSource } from "cesium";
const ds = await CzmlDataSource.load("/data/vehicle.czml");
viewer.dataSources.add(ds);
await ds.process("/data/vehicle-update.czml"); // append without clearing
1.143 以降では、CZML のパスに materialMode を設定して、固定のパスモードまたは時間によって変化するプロパティを指定できます。PORTIONS は、時間間隔またはサンプルに基づくマテリアルを対応するパスセグメントに適用し、WHOLE はシミュレーション時刻におけるマテリアルをパス全体に適用します。最適化された直接 API のパターンについては、cesiumjs-time-properties を参照してください。
const routePacket = {
id: "route",
path: {
materialMode: [
{ interval: "2026-07-15T12:00:00Z/2026-07-15T12:02:00Z", pathMode: "PORTIONS" },
{ interval: "2026-07-15T12:02:00Z/2026-07-15T12:04:00Z", pathMode: "WHOLE" },
],
resolution: 30,
material: [
{ interval: "2026-07-15T12:00:00Z/2026-07-15T12:02:00Z",
solidColor: { color: { rgba: [0, 255, 255, 255] } } },
{ interval: "2026-07-15T12:02:00Z/2026-07-15T12:04:00Z",
solidColor: { color: { rgba: [255, 165, 0, 255] } } },
],
},
};
GPX
import { GpxDataSource } from "cesium";
const ds = await GpxDataSource.load("/data/trail.gpx");
viewer.dataSources.add(ds);
viewer.zoomTo(ds);
CustomDataSource
import { CustomDataSource, Cartesian3, Color } from "cesium";
const customDs = new CustomDataSource("sensors");
customDs.entities.add({
position: Cartesian3.fromDegrees(-95, 40),
point: { pixelSize: 8, color: Color.LIME },
});
viewer.dataSources.add(customDs);
customDs.show = false; // toggle entire group visibility
エンティティのクラスタリング
import { GeoJsonDataSource, Color, VerticalOrigin, PinBuilder } from "cesium";
const ds = await GeoJsonDataSource.load("/data/facilities.geojson");
viewer.dataSources.add(ds);
ds.clustering.enabled = true;
ds.clustering.pixelRange = 40;
ds.clustering.minimumClusterSize = 3;
const pinBuilder = new PinBuilder();
ds.clustering.clusterEvent.addEventListener((entities, cluster) => {
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.verticalOrigin = VerticalOrigin.BOTTOM;
cluster.billboard.image = pinBuilder.fromText(`${entities.length}`, Color.VIOLET, 48).toDataURL();
});
親子の表示設定
parent.show = false に設定すると、個々の show フラグを変更せずに、すべての子孫が非表示になります。
const parent = viewer.entities.add({ name: "Group" });
viewer.entities.add({ parent, position: Cartesian3.fromDegrees(-90, 35), point: { pixelSize: 6, color: Color.RED } });
viewer.entities.add({ parent, position: Cartesian3.fromDegrees(-91, 36), point: { pixelSize: 6, color: Color.BLUE } });
parent.show = false; // both children disappear
parent.show = true; // both reappear
エンティティの説明とカスタムプロパティ
// InfoBox HTML: displayed when user clicks the entity
viewer.entities.add({
name: "Station Alpha",
position: Cartesian3.fromDegrees(-75.17, 39.95),
point: { pixelSize: 12, color: Color.CYAN },
description: `<table class="cesium-infoBox-defaultTable"><tr><th>Status</th><td>Active</td></tr></table>`,
properties: { population: 500000, category: "metro" },
});
// Read custom properties
// entity.properties.population.getValue() --> 500000
KML へのエクスポート
import { exportKml } from "cesium";
const result = await exportKml({ entities: viewer.entities, kmz: true });
// result.kmz is a Blob; result.kml is a string when kmz: false
const url = URL.createObjectURL(result.kmz);
17 種類すべてのグラフィックス
| グラフィックス | 主なプロパティ |
|---|---|
PointGraphics | pixelSize, color, outlineColor, outlineWidth |
BillboardGraphics | image, scale, rotation, sizeInMeters, heightReference |
LabelGraphics | text, font, fillColor, style, showBackground |
ModelGraphics | uri, scale, silhouetteColor, runAnimations, colorBlendMode |
PolygonGraphics | hierarchy, height, extrudedHeight, material, perPositionHeight |
PolylineGraphics | positions, width, material, clampToGround, arcType |
EllipseGraphics | semiMajorAxis, semiMinorAxis, rotation, extrudedHeight |
RectangleGraphics | coordinates (Rectangle), height, extrudedHeight |
BoxGraphics | dimensions (Cartesian3), material, outline |
CylinderGraphics | length, topRadius, bottomRadius |
EllipsoidGraphics | radii (Cartesian3) |
CorridorGraphics | positions, width, cornerType |
WallGraphics | positions, minimumHeights, maximumHeights |
PolylineVolumeGraphics | positions, shape (Cartesian2[]) |
PlaneGraphics | plane (Plane), dimensions (Cartesian2) |
PathGraphics | resolution, leadTime, trailTime, width, material, materialMode (1.143+), relativeTo (experimental) |
Cesium3DTilesetGraphics | uri |
PathGraphics.relativeTo(実験的、1.140+、#13223): 別のエンティティを基準とする参照フレームでパスを表示するか、エンティティのpositionのReferenceFrameとは異なる参照フレームでパスを表示します。たとえば、ECEF ではなく、移動する車両を基準としてドローンの軌跡を描画できます。実験的機能として指定されているため、シグネチャは変更される可能性があります。
PathGraphics.materialMode(1.143+):PathMode.PORTIONSを使用すると、移動するエンティティのパスに沿って、区間またはサンプルごとのマテリアルを保持できます。デフォルトのPathMode.WHOLEでは、現在時刻のマテリアルでパス全体が着色されます。この値自体もPropertyであるため、時間に応じて変化させることもできます。TypeScript 1.143 との互換性を保つには、パスのオプションオブジェクトを通じて設定してください。セグメント数を制御するには、cesiumjs-time-propertiesのresolutionを調整します。
主な列挙型
| 列挙型 | 値 |
|---|---|
HeightReference | NONE, CLAMP_TO_GROUND, RELATIVE_TO_GROUND |
HorizontalOrigin | LEFT, CENTER, RIGHT |
VerticalOrigin | TOP, CENTER, BOTTOM, BASELINE |
LabelStyle | FILL, OUTLINE, FILL_AND_OUTLINE |
ColorBlendMode | HIGHLIGHT, REPLACE, MIX |
PathMode | WHOLE, PORTIONS |
ShadowMode | DISABLED, ENABLED, CAST_ONLY, RECEIVE_ONLY |
ArcType | NONE, GEODESIC, RHUMB |
CornerType | ROUNDED, MITERED, BEVELED |
パフォーマンスのヒント
- エンティティをまとめて追加するときは
suspendEvents()/resumeEvents()を使用して、変更通知をまとめてください。 - 静的データには定数プロパティを優先してください。CesiumJS は変更されないエンティティを最適化します。
DistanceDisplayConditionを使用して、実用的な範囲を超えたエンティティを非表示にしてください。- 静的な図形が 10k 以上ある場合は Primitives に切り替えてください。Primitives ではエンティティごとのオーバーヘッドが発生しません。
- 点状のエンティティが多数ある DataSources では、クラスタリングを有効にしてください。
- 地形による遮蔽を防ぐには、ビルボードやラベルに
disableDepthTestDistanceを設定してください。 - 地面に固定するポリゴンでは、アウトラインを最小限にしてください。描画パスが追加で必要になります。
- 必要な場合に限り
clampToGroundを使用してください。地形に沿った細分化が必要になります。 - CZML の更新では、すべてを置き換える
load()ではなく、追加するprocess()で更新をまとめてください。 - 同一の画像を再生成しないよう、PinBuilder のキャンバスはキャッシュして再利用してください。
関連項目
- cesiumjs-camera —
flyTo、setView、Rectangleを使ったフレーミング。エンティティのターゲットがない場合に使用します - cesiumjs-time-properties — 時間変化するエンティティ属性に使用する SampledProperty、CallbackProperty、MaterialProperty の各タイプ
- cesiumjs-primitives — パフォーマンスが重要な静的ジオメトリ向けの低レベル Primitive API(
*Geometryクラス) - cesiumjs-interaction — ScreenSpaceEventHandler、Scene.pick、エンティティの選択やホバーのパターン