cesiumjs-viewer-setup について
cesiumjs-viewer-setupは、CesiumJSのViewerとシーンを初期化するためのリファレンスで、3D地球儀や地図アプリの開発者向けです。Viewer設定、地形や画像レイヤー、ジオコーディング、読み込んだコンテンツの表示範囲設定をまとめています。
主な機能
- 01ViewerとCesiumWidgetの初期化
- 02地形、画像、シーンの設定
- 03Ion、Google Maps、iTwinの設定
- 04ジオコーダーとViewer mixin
- 05読み込んだコンテンツへのカメラ設定
活用シーン
- 01カスタムUIや軽量なCesiumシーンの構築
- 02地形、画像、3D Tilesの設定
- 03読み込んだモデルやデータにカメラを合わせる
- 04ジオコーディングとドラッグ&ドロップ読み込みの設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cesiumgs/ cesiumjs-skills --skill cesiumjs-viewer-setupインストール後、Claude Code で/cesiumjs-viewer-setupを入力して読み込まれたか確認します。
詳細
CesiumJS Viewer とシーンのセットアップ
CesiumJS アプリケーションの初期化に関するリファレンスです。Viewer、CesiumWidget、Ion/GoogleMaps/ITwinPlatform の設定、ウィジェット、ファクトリーヘルパー、ジオコーダーサービス、Viewer のミックスイン、Credits、および関連する列挙型を扱います。
クイックスタート
import { Viewer, ImageryLayer, OpenStreetMapImageryProvider } from "cesium";
import "cesium/Build/Cesium/Widgets/widgets.css";
const viewer = new Viewer("cesiumContainer", {
baseLayer: new ImageryLayer(new OpenStreetMapImageryProvider({
url: "https://tile.openstreetmap.org/",
maximumLevel: 18,
})),
baseLayerPicker: false,
});
必須の HTML:<div id="cesiumContainer" style="width:100%;height:100vh"></div>
Cesium ion のデフォルト(Terrain.fromWorldTerrain、ImageryLayer.fromWorldImagery、createOsmBuildingsAsync、Google Photorealistic 3D Tiles)は、対象の実行環境で必要な ion または Google の利用権限がある場合にのみ使用してください。公開トークン不要の例では、明示的な公開プロバイダーと URL を指定した 3D Tiles を選択してください。
読み込んだコンテンツのフレーミング(重要)
タイルセット、モデル、またはデータソースを追加した後は、必ず明示的にフレーミングしてください。
デフォルトのオプションで構築した Viewer は、カメラが固定された地球のビューから開始します。追加したプリミティブに合わせて自動的にズームすることはありません。「灰色の地表しか見えない」または「アセットが隅に小さく表示される」という問題の最も一般的な原因は、これを忘れることです。
const tileset = await Cesium3DTileset.fromUrl(url);
viewer.scene.primitives.add(tileset);
// Pick ONE of:
await viewer.zoomTo(tileset); // instant fit to bounding sphere
await viewer.flyTo(tileset, { duration: 0 }); // animated; duration 0 = instant
viewer.zoomTo/viewer.flyTo が受け取るのは、Entity、Entity[]、EntityCollection、DataSource、ImageryLayer、Cesium3DTileset、VoxelPrimitive、Model、または TimeDynamicPointCloud です。これらは対象のバウンディングスフィアを使用します。そのため、任意のローカル座標系を持つタイルセットでも機能します。ECEF のカメラ位置を手動で計算すると、アセットを完全に見失うことがあります。
明示的なカメラ位置が必要な場合(例:方位角/ピッチの仕様を満たす場合)でも、viewer.zoomTo(target, headingPitchRange) を使用してください。範囲は推測するのではなく、バウンディングスフィアから導出されます。
import { HeadingPitchRange, Math as CesiumMath } from "cesium";
await viewer.zoomTo(tileset, new HeadingPitchRange(
CesiumMath.toRadians(45), // heading
CesiumMath.toRadians(-30), // pitch
/* range omitted -> auto-fit */
));
Ion とプラットフォームの設定
Cesium Ion
import { Ion } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN"; // required for ion assets
Ion.defaultServer = "https://your-ion-server.example.com/"; // optional: self-hosted
IonResource
import { IonResource, Cesium3DTileset } from "cesium";
const resource = await IonResource.fromAssetId(96188);
const tileset = await Cesium3DTileset.fromUrl(resource);
viewer.scene.primitives.add(tileset);
await viewer.zoomTo(tileset);
Google Maps Platform
import { GoogleMaps, createGooglePhotorealistic3DTileset, Viewer, IonGeocodeProviderType } from "cesium";
GoogleMaps.defaultApiKey = "YOUR_GOOGLE_MAPS_API_KEY"; // optional: without key, served via ion
const viewer = new Viewer("cesiumContainer", {
geocoder: IonGeocodeProviderType.GOOGLE, // required with Google 3D Tiles
});
const tileset = await createGooglePhotorealistic3DTileset({
onlyUsingWithGoogleGeocoder: true,
});
viewer.scene.primitives.add(tileset);
iTwin Platform(実験的)
import { ITwinPlatform, ITwinData } from "cesium";
ITwinPlatform.defaultAccessToken = "YOUR_ITWIN_TOKEN";
const tileset = await ITwinData.createTilesetForIModel(viewer, "imodel-id");
// 1.140+ (#13208): Reality Data of type GaussianSplat3DTiles is now supported
const splats = await ITwinData.createTilesetForRealityDataId(
iTwinId,
realityDataId,
ITwinPlatform.RealityDataType.GaussianSplat3DTiles,
);
viewer.scene.primitives.add(splats);
Viewer コンストラクターのオプション
new Viewer(container, options?) -- container は DOM 要素またはその文字列 ID です。
ウィジェットの切り替え
| オプション | デフォルト | 用途 |
|---|---|---|
animation | true | 再生コントロール |
baseLayerPicker | true | 画像/地形の切り替え |
fullscreenButton | true | 全画面表示の切り替え |
vrButton | false | WebVR の切り替え |
geocoder | IonGeocodeProviderType.DEFAULT | 検索バー(非表示にする場合は false) |
homeButton | true | ホームビューに戻す |
infoBox | true | エンティティ情報のポップアップ |
sceneModePicker | true | 2D/3D/Columbus の切り替え |
selectionIndicator | true | 選択マーカー |
timeline | true | 時間のスクラバー |
navigationHelpButton | true | マウス/タッチ操作のヘルプ |
projectionPicker | false | 透視投影/正投影の切り替え |
シーンとレンダリング
| オプション | デフォルト | 用途 |
|---|---|---|
sceneMode | SceneMode.SCENE3D | 初期シーンモード |
scene3DOnly | false | 3D に固定し、ジオメトリーインスタンスごとの GPU メモリを節約 |
shadows | false | 影の投影 |
terrainShadows | ShadowMode.RECEIVE_ONLY | 地形の影モード |
requestRenderMode | false | 変更時のみレンダリング |
maximumRenderTimeChange | 0.0 | レンダリング時のシミュレーション時間の最大差分 |
msaaSamples | 4 | MSAA(無効にする場合は 1) |
orderIndependentTranslucency | true | 透過描画の順序 |
mapMode2D | MapMode2D.INFINITE_SCROLL | 2D のスクロール動作 |
低電力向けまたはダッシュボード向けアプリでは、requestRenderMode: true と scene3DOnly: true を組み合わせてください。GPU の節約が求められるシナリオでは、一般に両方を併用する必要があります。
レイヤーと地形
| オプション | デフォルト | 用途 |
|---|---|---|
baseLayer | ImageryLayer.fromWorldImagery() | ベース画像(なしにする場合は false。その場合は baseLayerPicker: false が必要) |
terrain | なし | 非同期地形ヘルパー(terrainProvider とは併用不可) |
terrainProvider | EllipsoidTerrainProvider | 同期地形プロバイダー |
globe | new Globe() | 地球儀を表示しない場合は false(宇宙シーン向け) |
skyBox | 自動(WGS84) | false にすると空/太陽/月を無効化 |
skyAtmosphere | 自動(WGS84) | false にすると地平線の輝きを無効化 |
最小ビューアー(ウィジェットなし)
import { Viewer, ImageryLayer, OpenStreetMapImageryProvider } from "cesium";
const viewer = new Viewer("cesiumContainer", {
baseLayer: new ImageryLayer(new OpenStreetMapImageryProvider({
url: "https://tile.openstreetmap.org/",
maximumLevel: 18,
})),
animation: false, baseLayerPicker: false, fullscreenButton: false,
geocoder: false, homeButton: false, infoBox: false,
sceneModePicker: false, selectionIndicator: false,
timeline: false, navigationHelpButton: false,
});
CesiumWidget(軽量な代替手段)
UI ウィジェットも Knockout への依存もありません。カスタム UI や埋め込みに適しています。
import { CesiumWidget, Ion } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN";
const widget = new CesiumWidget("cesiumContainer", { shouldAnimate: true });
// Exposes: widget.scene, widget.camera, widget.entities
SceneMode Enum
| 値 | 説明 |
|---|---|
SceneMode.SCENE3D | 標準の 3D 地球儀(デフォルト) |
SceneMode.SCENE2D | 真上から見た正投影図 |
SceneMode.COLUMBUS_VIEW | 高さのある 2.5D の平面地図 |
SceneMode.MORPHING | モード間を遷移中 |
import { Viewer, SceneMode } from "cesium";
const viewer = new Viewer("cesiumContainer", { sceneMode: SceneMode.SCENE2D });
viewer.scene.morphTo3D(2.0); // animated transition
viewer.scene.morphToColumbusView(2.0);
シーンの設定
const scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true; // entities interact with terrain
scene.globe.enableLighting = true; // sun-based lighting
// Key sub-objects
scene.camera; // Camera
scene.primitives; // PrimitiveCollection
scene.groundPrimitives; // PrimitiveCollection (ground-clamped)
scene.imageryLayers; // ImageryLayerCollection
scene.postProcessStages;
scene.requestRender(); // trigger frame in requestRenderMode
重要:対応するコンストラクターオプションが false に設定されている場合は、scene.globe.* や scene.skyAtmosphere.* に絶対に触れないでください。 Viewer オプションでこれらを無効にすると、シーン上の対応するプロパティは undefined になり、.enableLighting、.depthTestAgainstTerrain、.show などのフィールドにアクセスすると、TypeError: Cannot set properties of undefined がスローされます。宇宙空間のシーンでは、コンストラクターで一度だけ設定し、その後これらのプロパティを変更しないでください(下記の「宇宙空間のシーン」を参照)。
ファクトリーヘルパー
createOsmBuildingsAsync
import { createOsmBuildingsAsync, Cesium3DTileStyle } from "cesium";
// Default styling (colors from OSM tags)
const tileset = await createOsmBuildingsAsync();
viewer.scene.primitives.add(tileset);
// Custom style
const styled = await createOsmBuildingsAsync({
style: new Cesium3DTileStyle({
color: { conditions: [
["${feature['building']} === 'hospital'", "color('#0000FF')"],
[true, "color('#ffffff')"],
]},
}),
});
createGooglePhotorealistic3DTileset
import { createGooglePhotorealistic3DTileset, IonGeocodeProviderType } from "cesium";
// Must use Google geocoder
const viewer = new Viewer("cesiumContainer", { geocoder: IonGeocodeProviderType.GOOGLE });
const tileset = await createGooglePhotorealistic3DTileset({ onlyUsingWithGoogleGeocoder: true });
viewer.scene.primitives.add(tileset);
Terrain.fromWorldTerrain / fromWorldBathymetry
terrain コンストラクターオプションにはこちらを推奨します。エラーイベントに対応し、処理をブロックしません。
import { Viewer, Terrain } from "cesium";
// World terrain with normals and water
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain({ requestVertexNormals: true, requestWaterMask: true }),
});
// Bathymetry (ocean floor)
const viewer2 = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldBathymetry({ requestVertexNormals: true }),
});
Terrain イベントの処理
import { Terrain, CesiumTerrainProvider } from "cesium";
const terrain = new Terrain(CesiumTerrainProvider.fromUrl("https://my-terrain.example.com"));
viewer.scene.setTerrain(terrain);
terrain.readyEvent.addEventListener((provider) => {
viewer.scene.globe.enableLighting = true;
});
terrain.errorEvent.addEventListener((error) => console.error("Terrain failed:", error));
createWorldTerrainAsync / createWorldImageryAsync
より低レベルの API で、生のプロバイダーを返します。プロバイダーを直接必要とする場合に使用します。
import { createWorldTerrainAsync, createWorldImageryAsync, IonWorldImageryStyle } from "cesium";
const terrainProvider = await createWorldTerrainAsync({ requestVertexNormals: true });
viewer.terrainProvider = terrainProvider;
const imageryProvider = await createWorldImageryAsync({ style: IonWorldImageryStyle.AERIAL_WITH_LABELS });
IonWorldImageryStyle:AERIAL(デフォルト) | AERIAL_WITH_LABELS | ROAD
ジオコーダーの設定
geocoder オプションには、false、IonGeocodeProviderType、または GeocoderService[] を指定できます。
IonGeocodeProviderType:DEFAULT | GOOGLE(Google タイルでは必須) | BING
import { Viewer, CartographicGeocoderService, IonGeocoderService, OpenCageGeocoderService } from "cesium";
// Multiple services (searched in order)
const viewer = new Viewer("cesiumContainer", {
geocoder: [
new CartographicGeocoderService(), // accepts "lat, lon" input
new IonGeocoderService({ scene: viewer.scene }),
],
});
カスタム GeocoderService
const myGeocoder = {
async geocode(input, type) {
// type: GeocodeType.SEARCH or GeocodeType.AUTOCOMPLETE
const resp = await fetch(`https://api.example.com/search?q=${input}`);
const data = await resp.json();
return data.map((item) => ({
displayName: item.name,
destination: Cartesian3.fromDegrees(item.lon, item.lat),
}));
},
};
const viewer = new Viewer("cesiumContainer", { geocoder: [myGeocoder] });
Viewer ミックスイン
import { Viewer, viewerDragDropMixin, viewerCesium3DTilesInspectorMixin,
viewerCesiumInspectorMixin, viewerPerformanceWatchdogMixin, viewerVoxelInspectorMixin } from "cesium";
const viewer = new Viewer("cesiumContainer");
// Drag-and-drop CZML/GeoJSON/KML loading
viewer.extend(viewerDragDropMixin, { dropTarget: "cesiumContainer", clearOnDrop: true });
viewer.dropError.addEventListener((handler, name, error) => console.error(error));
viewer.extend(viewerCesium3DTilesInspectorMixin); // 3D Tiles debug panel
viewer.extend(viewerCesiumInspectorMixin); // general scene inspector
viewer.extend(viewerPerformanceWatchdogMixin); // low-FPS warning
viewer.extend(viewerVoxelInspectorMixin); // voxel debug panel
主な Viewer のプロパティとメソッド
| プロパティ | 型 |
|---|---|
viewer.scene | Scene |
viewer.camera | Camera |
viewer.entities | EntityCollection |
viewer.dataSources | DataSourceCollection |
viewer.imageryLayers | ImageryLayerCollection |
viewer.terrainProvider | TerrainProvider |
viewer.clock / clockViewModel | Clock / ClockViewModel |
viewer.canvas | HTMLCanvasElement |
viewer.screenSpaceEventHandler | ScreenSpaceEventHandler |
viewer.selectedEntity / trackedEntity | Entity |
viewer.shadows | boolean |
viewer.resolutionScale | number(デフォルト 1.0) |
await viewer.flyTo(entity, { duration: 3.0, offset: headingPitchRange }); // animated
await viewer.zoomTo(tileset); // instant; uses bounding sphere
viewer.destroy(); // free all resources
クレジットと FrameRateMonitor
import { Credit, FrameRateMonitor } from "cesium";
// Custom credit (showOnScreen = true)
viewer.creditDisplay.addStaticCredit(new Credit("Data by Example Corp", true));
// Monitor frame rate
const monitor = FrameRateMonitor.fromScene(viewer.scene);
monitor.lowFrameRate.addEventListener(() => console.warn("Low FPS"));
monitor.nominalFrameRate.addEventListener(() => console.log("FPS recovered"));
よく使われるパターン
地形と OSM 建物を含む本番用 Viewer
import { Ion, Viewer, Terrain, createOsmBuildingsAsync, Cartesian3, Math as CesiumMath } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN";
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain(), animation: false, timeline: false,
});
viewer.scene.primitives.add(await createOsmBuildingsAsync());
viewer.scene.camera.flyTo({
destination: Cartesian3.fromDegrees(-74.019, 40.6912, 750),
orientation: { heading: CesiumMath.toRadians(20), pitch: CesiumMath.toRadians(-20) },
});
サンプル 3D Tileset の読み込みと表示範囲の調整
タイルセットのローカル座標系が不明な場合(サンプルアセットや離散 LOD のデモなど)、ECEF カメラ位置を手計算しないでください。アセットを見逃し、灰色の空のサーフェスが描画されます。HeadingPitchRange を指定して viewer.zoomTo を使用し、タイルセットのバウンディングスフィアに合わせた表示を導出してください。
import { Cesium3DTileset, HeadingPitchRange, Math as CesiumMath } from "cesium";
const tileset = await Cesium3DTileset.fromUrl(url);
viewer.scene.primitives.add(tileset);
await viewer.zoomTo(
tileset,
new HeadingPitchRange(
CesiumMath.toRadians(45),
CesiumMath.toRadians(-30),
// omit range -> Cesium auto-fits the bounding sphere
),
);
宇宙空間のシーン(地球儀なし)
コンストラクターオプションのみで地球儀と大気を無効にしてください。シーンの globe と skyAtmosphere プロパティは undefined になるため、後から viewer.scene.globe.<anything> = ... や viewer.scene.skyAtmosphere.show = false を実行すると、Cannot set properties of undefined がスローされます。ライティング、地形に対する深度テスト、大気の表示設定などはコンストラクターで設定するか、宇宙空間のシーンでは設定を省略してください。
const viewer = new Viewer("cesiumContainer", {
globe: false, // viewer.scene.globe will be undefined
skyAtmosphere: false, // viewer.scene.skyAtmosphere will be undefined
baseLayerPicker: false,
baseLayer: false, // no imagery layer is needed without a globe
});
// Safe post-construction tweaks (skyBox/sun/moon remain defined):
viewer.scene.skyBox.show = true; // default star field
viewer.scene.sun.show = false;
viewer.scene.moon.show = false;
// DO NOT do this, throws because globe/skyAtmosphere are undefined:
// viewer.scene.globe.enableLighting = true;
// viewer.scene.skyAtmosphere.show = false;
明示的なレンダリングモード(低消費電力ダッシュボード)
2D や Columbus View が不要な場合は、scene3DOnly: true と組み合わせてください。これが標準的な低 GPU 負荷の設定です。
const viewer = new Viewer("cesiumContainer", {
requestRenderMode: true,
maximumRenderTimeChange: Infinity,
scene3DOnly: true,
animation: false,
timeline: false,
});
// Call viewer.scene.requestRender() after programmatic changes
カスタムベースレイヤー
import { Viewer, ImageryLayer, OpenStreetMapImageryProvider } from "cesium";
const viewer = new Viewer("cesiumContainer", {
baseLayerPicker: false,
baseLayer: new ImageryLayer(new OpenStreetMapImageryProvider({
url: "https://tile.openstreetmap.org/",
})),
});
Web Mercator を使った Columbus View
import { Viewer, SceneMode, WebMercatorProjection } from "cesium";
const viewer = new Viewer("cesiumContainer", {
sceneMode: SceneMode.COLUMBUS_VIEW, mapProjection: new WebMercatorProjection(),
});
パフォーマンスのヒント
- 静的な状態が大半を占めるアプリでは、
requestRenderMode: trueを設定します。CPU/GPU の使用量とバッテリー消費を抑えられます。変更後はscene.requestRender()を呼び出します。 - 2D/Columbus View が不要な場合は、
scene3DOnly: trueを使用します。ジオメトリインスタンスごとの GPU メモリを節約できます。ダッシュボードや低電力のシナリオでは、通常requestRenderModeと併せて設定する必要があります。 - 使用しないウィジェット(
animation: false、timeline: false)を無効にして、DOM のオーバーヘッドを減らします。 - 低電力デバイスでは
msaaSamples: 1を設定します。デフォルトの4は画質とのバランスを取った値です。 - HiDPI ディスプレイでは
resolutionScaleを下げる(例:0.75)と、フレームレートが向上します。 await createWorldTerrainAsync()よりTerrain.fromWorldTerrain()を優先します。ノンブロッキングで、エラーイベントを利用できます。- 地形で
requestVertexNormals: trueを有効にすると、ほとんどコストをかけずに適切なライティングを実現できます。 - DOM から削除するときは
viewer.destroy()を呼び出し、WebGL コンテキストを解放します。 - イメージレイヤーは 2~3 個に制限します。追加するたびに、フラグメントごとのテクスチャ検索が増えます。
フレーミングのチェックリスト(何も表示されない/フレーム外への描画を防ぐ)
ビューアーの設定タスクを完了とする前に、次の項目を確認します。
- タイルセット、モデル、GeoJSON/KML/CZML データソース、またはエンティティコレクションを追加した後、
await viewer.zoomTo(target)またはawait viewer.flyTo(target)を呼び出していること。 - ローカル座標系が不明なタイルセットでは、カメラの位置を手動で選んだ
Cartesian3.fromDegrees(...)ではなく、バウンディングスフィア(HeadingPitchRange)から導出していること。 - シナリオで heading/pitch が指定されている場合、推測した目的地を使って
camera.flyToに設定するのではなく、HeadingPitchRangeを介してzoomTo/flyToに渡していること。 - シナリオでアセットの下に地図を表示する想定の場合、必要なベースイメージレイヤーが実際に存在すること(count == 1)。
- コンストラクターオプションで
globe: falseまたはskyAtmosphere: falseが設定されている場合、それ以降のコードでviewer.scene.globe.*またはviewer.scene.skyAtmosphere.*にアクセスしないこと。どちらもundefinedであり、アクセスすると例外が発生します。
関連項目
- cesiumjs-camera -- カメラの位置設定、flyTo、lookAt、ナビゲーションの制約
- cesiumjs-entities -- Entity API、データソース、GeoJSON/KML/CZML の読み込み
- cesiumjs-imagery -- イメージプロバイダー、レイヤー管理、分割画面
- cesiumjs-terrain-environment -- 地形プロバイダー、Globe、大気、空、ライティング