はじめに
Tauriはクロスプラットフォーム対応のデスクトップ、モバイルアプリケーション開発フレームワークです。本記事ではTauriでCesium.jsを使ってデスクトップアプリケーションにCesium Globeを表示する方法について説明します。
Tauriのアプリケーション開発ではNode.jsが必要になります。また、TauriはバックエンドにRustを使用するためRustのインストールも必要になります。ただ、Cesiumの表示を行うだけであればRustのコードを記述する必要はありません。
プロジェクト作成
今回の例ではUIテンプレートにReactを使うものとします。
> npm create tauri-app@latest
コマンドを入力すると質問に答える形でプロジェクトの基本設定を行います。本記事では以下のようにしました。
- Project name : cesium-tauri
- Language : Typescript / Javascript
- Package manager : npm
- UI template : React
- UI flavor : Typescript
プロジェクトを作成するとプロジェクト名のディレクトリが作成されるので、ディレクトリへ移動してnpm installを一発入れてからnpm run tauri devとコマンドを入力してみます。問題がなければ初期状態のプログラムが実行されるはずです。
Cesiumの表示
TauriのプロジェクトではビルドツールとしてViteを使用します。
Cesiumのアセットをコピー
node_modules/cesium/Build/Cesium以下にあるCesiumアセットをpublic/cesium/に全てコピーします。
vite-plugin-cesiumを使うべきところかもしれませんが、筆者の環境では正しく動作しませんでした。
vite.config.ts
まずはプロジェクトディレクトリのトップにあるvite.config.tsを以下のように記述します。
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
server: {
port: 1420,
strictPort: true,
watch: {
ignored: ["**/src-tauri/**"],
},
},
build: {
// 最新のJavaScript構文で出力
target: "esnext",
// Cesium.jsをコード分割によって初期ロードを最適化
rollupOptions: {
output: {
manualChunks: {
cesium: ["cesium"],
},
},
},
},
optimizeDeps: {
// 大きなライブラリの初回読み込みを高速化
include: ["cesium"],
// 依存関係の事前バンドル時もesnextターゲットを使用
esbuildOptions: {
target: "esnext",
},
},
});
src-tauri/tauri.conf.json
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "cesium-tauri",
"version": "0.1.0",
"identifier": "com.yamate.cesium-tauri",
"build": {
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "npm run build",
"frontendDist": "../dist"
},
"app": {
"windows": [
{
"title": "cesium-tauri",
"width": 800,
"height": 600
}
],
"security": {
"csp": null,
// CSPの設定をとりあえずは緩和
"dangerousDisableAssetCspModification": true
},
// 開発中はtrueでいいのか?
"withGlobalTauri": true
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}
この辺の設定は改良の余地があるかもしれません。
src/App.tsx
Cesiumを表示する部分になります。
import { useEffect, useRef } from "react";
import * as Cesium from "cesium";
import "cesium/Build/Cesium/Widgets/widgets.css";
import "./App.css";
// Cesiumのベースパスを設定(重要!)
(window as any).CESIUM_BASE_URL = "/cesium/";
// Cesium Ion アクセストークン(自分のトークンに置き換えてください)
// https://ion.cesium.com/tokens で取得できます
Cesium.Ion.defaultAccessToken = "your-access-token"; // アクセストークンは必須
function App() {
const cesiumContainer = useRef<HTMLDivElement>(null);
const viewerRef = useRef<Cesium.Viewer | null>(null);
useEffect(() => {
if (!cesiumContainer.current) return;
const initViewer = async () => {
// Cesium Viewerの初期化
viewerRef.current = new Cesium.Viewer(cesiumContainer.current as HTMLDivElement, {
geocoder: false,
homeButton: true,
sceneModePicker: true,
fullscreenButton: false,
});
// 地形データを追加(せっかくなのでJapan Regional Terrain)
try {
viewerRef.current.terrainProvider = await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062, {
requestWaterMask: true, // 水面マスク
requestVertexNormals: true, // 頂点法線を要求
});
} catch (error) {
console.error("Terrain loading error.", error);
}
}
initViewer();
// クリーンアップ
return () => {
if (viewerRef.current) {
viewerRef.current.destroy();
viewerRef.current = null;
}
};
}, []);
return (
<div className="app-container">
<div ref={cesiumContainer} className="cesium-container" />
</div>
);
}
export default App;
CesiumのコードはinitViewer()の中に記述するとよいでしょう。
src/App.css
@media (prefers-color-scheme: dark) {
:root {
/* ウィンドウのマージンの部分をダークモード */
background-color: #2f2f2f;
}
}
/*
ウィンドウのマージンの関係で、コンテナを少し小さくする
100にするとスクロールバーがでてしまう。
(どこかにウィンドウのマージンを0にするところがあるのかも?)
*/
.app-container {
width: 97vw;
height: 97vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.cesium-container {
flex: 1;
width: 100%;
height: 100%;
}
以上が最低限のコードになります。
実行とビルド
ココまでで実行してみます。以下のように表示されれば成功です。
ビルドを行うには以下のコマンドを実行します。
> npm run tauri build
実行すると、src-tauri/target/release以下に実行ファイルが作成されています。
また、src-tauri/target/release/bundle/以下にmsiとnsisというフォルダがあり、それぞれに.msiと.exeのインストーラが作成されます。
あくまで筆者の体感ですが、起動はかなり早い気がします。

