/ Technical Architecture Overview

OrthoMap — Technical Architecture

正射影(球体ビュー)に特化した WebGL2 マップレンダリングフレームワーク
Worker ベース並列パイプライン · OffscreenCanvas · Gint / GeoPBF / AltPBF 統合

Table of Contents
  1. アーキテクチャ概観
  2. 正射影と操作系
  3. Worker 通信プロトコル
  4. Base レイヤー — WebGL2 球体描画 + タイル
  5. BorderLines レイヤー — Gint 軽量ライン描画
  6. Accessories レイヤー — Canvas2D オーバーレイ
  7. Gint レイヤー — フル WebGL2 ベクター描画
  8. 状態管理・ガジェット

1. アーキテクチャ概観

OrthoMap はメインスレッドに投影演算・イベント処理・レイヤー管理のみを置き、 すべての描画を OffscreenCanvas + Web Worker に委譲する設計である。 各レイヤーは独立した Worker 上で動作し、メインスレッドへの描画ブロッキングがゼロになる。

Canvas2D Accessories stars · constellations · night · globe minimap · scale · clock(border.js Worker)
↑ オーバーレイ(最前面)
WebGL2 BorderLines graticule · 国境線 · 海上境界 · 地理線(gintBorder.js Worker)
↑ ベクターオーバーレイ
WebGL2 OrthoMapGL ベース球体テクスチャ + スライプルタイル(base.js Worker)
↕ ユーザー追加レイヤー(createLayer / createRemoteLayer)
Worker Gint レイヤー 任意 GeoPBF → WebGL2 描画・hover picking・ポリゴン塗り(gint.js Worker)

初期化フローは 3 ステップで完結する。

// index.js — エントリーポイント
const map = await orthoMap({
	target: d3.select("#container"),  // 省略時は body
	baseName: "osm.street",
	center: [139.7, 35.7],
	zoom: 4,
	accessories: { stars: { maxCount: 500 } },
	gadgets: false,
});

// 内部シーケンス:
// 1. orthographic(map, opts)  — 投影・イベント・操作系セットアップ
// 2. createLayers(map, opts)  — Worker 起動・3 レイヤー生成
// 3. createGadgets(map)       — UI コンポーネント登録

2. 正射影と操作系

2.1 スケール ↔ ズーム変換

D3 の geoOrthographic は球体の半径をスクリーンピクセルで表す scale を持つ。 OrthoMap はこれをウェブ地図標準のズームレベルに変換する。

scale = 2zoom × (256 / 2π)
zoom = log2(scale / (256 / 2π))
256 / 2π ≈ 40.74(タイルサイズ256px基準)

ズーム 5.5(threshold)を境に、それ以下はベース球体画像のみ、それ以上はスライプルタイルを重ねる。

2.2 Versor 四元数によるパン・ズーム・回転

マウスドラッグ・ピンチ操作は D3 の zoom イベントをベースとし、 球面上の正確な追従のために versor(単位四元数) を用いる。

// ドラッグ開始: タッチ点の球面座標をデカルト3Dへ
v0 = cartesian(proj.invert(pt0));  // [lng,lat] → [x,y,z]
q0 = versor(r0 = proj.rotate());  // 現在回転を四元数化

// ドラッグ中: 球面上の最小回転を四元数合成
const v1 = cartesian(proj.rotate(r0).invert(pt));
const q1 = multiply(q0, delta(v0, v1));
proj.rotate(rotation(q1));

2 点ピンチ時は指の角度差を追加の四元数で合成することで Z 軸回転(地図の傾き) も同時に操作できる。

Ctrl + ホイール:カーソル中心 Z 回転

Ctrl または Meta キー押下時のホイールは カーソル位置を中心に球を Z 軸回転させる。 カーソルの画面座標からカーソルまでの球面ベクトル [x,y,z] を求め、 これを回転軸とする四元数を現在の回転に合成する。 単純な camera rotate ではなく球体上の実点を軸とした物理的な回転である。

2.3 flyToFeature / zoomToFeature

両関数はアニメーション中に別操作が割り込んだ場合に即キャンセルできるよう flyTicket(単調増加カウンタ)で制御する。

関数アルゴリズム特徴
flyToFeature d3.interpolateZoom(ズームアウト→移動→ズームイン)+ 線形イージング 長距離移動時に「空を飛ぶ」ような弧を描く
zoomToFeature 2 フェーズ:① threshold zoom まで回転移動、② 目的地でズームイン タイル不要領域での移動 → 到着後のズームインでタイル読み込みを最小化
// zoomToFeature — 2フェーズ構成
// Phase1: 移動中は zoom 5.5 まで(travelMs ≈ 距離 × 2500ms)
const sTrav = min(s1, zval2scale(5.5));
// Phase2: 到着後 2000ms でズームイン(600ms オーバーラップ)
proj.scale(s0 + (sTrav - s0) * tRotEased   // 移動フェーズ
			 + (s1  - sTrav) * easeCubicInOut(tZoom)); // ズームフェーズ

2.4 イベントシステム

D3 Dispatch をベースに、ユーザー登録(無名)とシステム登録(名前付き)を分けた API を提供する。

// ユーザーイベント登録 — 自動採番でネームスペース管理
const handler = map.onClick(e => console.log(e.lng, e.lat));
handler.destroy(); // 登録解除

// イベント種類
// Enter / Move / Leave / Drop / Click / ContextMenu
// Drawing / Drawn / Resize / Change / LoadStart / LoadEnd

// Move / Click には標高が付く(AltPBF 統合)
// e = { lng, lat, alt, x, y, shiftKey, metaKey }

3. Worker 通信プロトコル

各レイヤーは OffscreenCanvas.transferControlToOffscreen() で Canvas の所有権を Worker に移譲し、 メインスレッドとは postMessage のみで通信する。描画ループ全体が Worker 内で完結する。

Main Thread → Worker
init — offscreen / dpr / workers
set — データ投入(cmd 別)
drawing — scale / rotate / panning
drawn — パン終了後の確定描画
move — カーソル座標
resize — width / height
destroy — Worker 終了
Worker → Main Thread
{action:"done", type:"init"}
{action:"done", type:"set"}
{action:"done", type:"resize"}
{action:"identify", featureId}
{action:"click", featureId, lng, lat}
{action:"redraw"} — context restored 後
Drawing / Drawn の分離

drawing はパン・ズーム中にフレームごとに飛ぶ「即時描画」命令であり、 簡易品質での高速描画を目的とする(タイルの新規読み込みはしない)。 drawn はポインタが止まったときに一度だけ送られる「確定描画」命令で、 FBO への高品質レンダリング・picking バッファ更新など重い処理はここで行う。

set メッセージは描画用バイナリデータを含む場合、Transferable として送ることでゼロコピー転送する。

// rawBuffers が含まれる場合のみ Transferable 転送
if (prop?.rawBuffers) {
	const { rawBuffers, ...rest } = prop;
	worker.postMessage({ type: "set", cmd, data, prop: rest, rawBuffers }, rawBuffers);
}

4. Base レイヤー — WebGL2 球体描画 + タイル

base.js Worker は 全球等矩形画像(8192×4096) をテクスチャとして球体に貼り付け、 ズームイン時はスライプルタイルを上から重ねる 2 段構成を取る。

4.1 GPU 側の正射影テクスチャサンプリング

フラグメントシェーダー内でピクセルの画面座標から球面座標を逆算し、等矩形テクスチャを直接サンプリングする。 CPU 側での投影変換やバーテックスバッファは不要になる。

// GLSL Fragment Shader (baseFs) — 正射影の逆変換
float x = (gl_FragCoord.x - translate.x) / scale;
float y = (translate.y  - gl_FragCoord.y) / scale;
float rho = sqrt(x*x + y*y);
if (rho <= 1.0) {                          // 球体円内のみ
	float c = asin(rho);
	float lng = atan(x * sin(c), rho * cos(c));
	float lat = asin(y * sin(c) / rho);
	applyRotation(rx, ry, rz, lng, lat);   // ユーザー回転を適用
	vec2 uv = vec2((lng + pi) / (2.0*pi), (lat + pi/2.0) / pi);
	outColor = texture(u_image, uv);
} else { discard; }                       // 球体外はフラグメント破棄
テクスチャラップモード

ベーステクスチャは経度方向(S 軸)を REPEAT、緯度方向(T 軸)を CLAMP_TO_EDGE に設定する。 これにより経度 ±180° の日付変更線を跨ぐ描画でシームが発生しない。 タイルテクスチャは隣タイルとの滲みを防ぐため両軸 CLAMP_TO_EDGE

4.2 タイル読み込みパイプライン

タイル Worker プール(デフォルト 4 並列)が URL 経由で画像を fetch し、ImageBitmap に変換して createTileTexture で GL テクスチャ化する。

// タイル優先度: 画面中央に近いタイルを先にロード
ents.sort((a, b) => a[4] - b[4])  // [4] = 中心距離
	.forEach(([x, y, zo, pos, dist]) => {
		// zo = 極方向オフセット(Y2T/Y4T テーブルで決定)
		// 希望ズームになければ z-1, z-2, z-3 のキャッシュを代用
		for (let dz of [0, 1, 2, 3]) {
			const z = Z0 - (zo + dz); if (z < 0) continue;
			const img = TileTub.get(name);
			if (img) { /* UV を親タイル領域に変換して描画 */ return; }
		}
	});

Y2T / Y4T テーブル: 高緯度タイルは Mercator 投影の歪みにより表示面積が極端に小さくなる。 これを補正するためズームレベルごとに緯度方向の LOD オフセット(zo)を定義した定数テーブルで、 極付近タイルを 1〜2 ズーム落としてロードする。

4.3 ベースマップ一覧

Nameベース球体画像タイルソースMaxZoom
whiteEarthwhiteEarth.webpなし7
google.streetnaturalEarth.webpGoogle Maps(lyrs=m)22
google.satellitegoogle.satellite.webpGoogle Maps(lyrs=s)22
osm.streetnaturalEarth.webpOpenStreetMap JP19
osm.satelliteosm.satellite.webpBing Maps(四分木インデックス)19
cyberjapan.stdnaturalEarth.webp国土地理院(日本域)+ OSM(域外)19
Firefox 対応

Firefox では createImageBitmap(blob) の結果が WebGL テクスチャとして正常に扱えない問題がある。 UA 判定により OffscreenCanvas を中間バッファとして描画し、 transferToImageBitmap() で再変換する workaround が入っている。

5. BorderLines レイヤー — Gint 軽量ライン描画

gintBorder.js は Gint の描画機能のうち ライン描画のみ を実装した軽量版である。 hover picking・ポリゴン塗り・FBO は持たず、固定スタイルの複数データセットを 1 パスで描く。

5.1 4 データセット × 4 スタイル

// 4 レイヤーの Gint データ(GeoPBF 経由でロード)
const geoNames = [
	"ne_110m_graticules_10",               // 経緯線 10°グリッド
	"ne_50m_admin_0_boundary_lines_land",   // 国境線
	"ne_50m_admin_0_boundary_lines_maritime_indicator", // 海上境界
	"ne_50m_geographic_lines",              // 赤道・回帰線 等
];

// 各データセットの描画スタイル(ダッシュはスクリーンピクセル固定)
const BORDER_GL_STYLES = [
	{ color: [1.0, 1.0, 1.0, 0.6], lineWidth: 1.0, dash: [0, 0] }, // graticule (solid)
	{ color: [1.0, 1.0, 1.0, 1.0], lineWidth: 1.0, dash: [4, 2] }, // 国境線
	{ color: [0.5, 0.5, 1.0, 0.8], lineWidth: 0.8, dash: [4, 2] }, // maritime
	{ color: [1.0, 1.0, 1.0, 0.6], lineWidth: 0.8, dash: [4, 2] }, // geographic
];

5.2 ダッシュのスクリーンピクセル固定

ダッシュ長はズームに関係なく常に同じ視覚サイズになるよう、頂点シェーダー内で v_dist_base = vertex_index × scale × sin(1°) として累積距離を計算する。 スクリーン座標でのピクセル距離が一定なので、ズーム変化でダッシュパターンが変形しない。

5.3 アルファ合成(blendFuncSeparate)

ライン同士が重なった際に半透明のアルファが積み重なってしまう問題を防ぐため、 blendFuncSeparate でカラーチャンネルと alpha チャンネルのブレンドを分離する。

gl.blendFuncSeparate(
	gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,  // RGB: 通常アルファブレンド
	gl.ONE,       gl.ONE_MINUS_SRC_ALPHA   // A: 元 alpha を保持
);

5.4 地平線またぎポリゴンの処理(VS_STENCIL)

ステンシルパス用の頂点シェーダーは、地球の裏面(z < 0)に回った頂点を NDC 原点 (0,0) に潰さず、地平線円(半径 = u_scale)の上に押し出す。 これにより国境線が地平線をまたぐポリゴンでも閉じた扇形が正しく構成され、 塗りつぶしに破綻が生じない。

// GLSL VS_STENCIL — 裏面頂点の地平線押し出し
if (p.z < 0.0) {
	vec2 v = p.xy - u_viewport * 0.5;
	float d = length(v);
	gl_Position = d < 1e-4
		? vec4(0.0, 0.0, 0.0, 1.0)  // 原点直上は原点へ
		: toNDC(u_viewport * 0.5 + v * (u_scale / d));  // 地平線円上へ
	return;
}

6. Accessories レイヤー — Canvas2D オーバーレイ

border.js Worker は Canvas2D コンテキストで動作し、 天文データ・地図表示補助情報を 1 秒インターバルタイマーで更新する。

6.1 恒星時(グリニッジ恒星時 = GST)

星・星座線の描画には現在時刻に対応する空の向きが必要で、GST を計算する。

GST = (18.697374 + 24.0657098 × T) × 15 mod 360
T = J2000.0 からのユリウス日(= (UNIX_ms / 86400000) + 2440587.5 − 2451545.0)

赤経(Right Ascension)から GST を引いた時角(Hour Angle)を使い、球面天文座標から スクリーン 2D 座標に変換する。

6.2 星(draw_stars)

恒星カタログ(stars.6)の各星を赤経・赤緯 → スクリーン座標に変換し、 B-V カラーインデックスから色を決定、等級から半径と透明度を計算する。

// B-V → 星の色(温度スペクトル)
const bvColor = bv =>
	bv < -0.3 ? "#b2c8ff" :  // O 型 — 青白
	bv <  0.0 ? "#d9e2ff" :  // B 型 — 青白
	bv <  0.3 ? "#f8faff" :  // A 型 — 白
	bv <  0.6 ? "#fff8f0" :  // F 型 — 黄白
	bv <  0.8 ? "#fff2c8" :  // G 型 — 黄(太陽)
	bv <  1.1 ? "#ffe0b5" :  // K 型 — 橙
				 "#ffab91";   // M 型 — 赤

// 等級 → 半径・透明度
radius = (9 - mag) * 0.20;   // 明るい星ほど大きい
alpha  = 1 - mag / 15;       // 明るい星ほど不透明

6.3 星座線(draw_constellations)

星座線は赤経・赤緯ペアのリスト(MultiLineString)として格納されており、 球面座標 → デカルト3D → 球面投影変換で各点の可視性を判定してから描画する。

// 赤道座標 (ra, dec) → 球面投影 (px, py)
l  = ra - skyRot;                   // 時角
z  = sinφ*sinδ + cosφ*cosδ*cos(l); // z < 0 なら地平線以下
x  = cosδ * (-sin(l));
y  = cosφ*sinδ - sinφ*cosδ*cos(l);
px = cx + sr * (x*cosγ - y*sinγ);  // sr = 球体半径より大きなスカイドーム半径
py = cy - sr * (x*sinγ + y*cosγ);

6.4 メシエ天体(draw_messier)

天体の種類(type)に応じてシンボルを描き分ける。

type名称シンボル
gc球状星団円 + 十字
gx / gg銀河楕円
oc散開星団破線円
その他星雲 等矩形

6.5 ミニマップグローブ(draw_globe)

画面四辺を各 30 点ずつサンプリング(計 120 点)して地理座標に逆変換し、 ミニグローブ投影に再投影した多角形として視野領域(reticle)を描画する。

// viewport 四辺の地理座標サンプリング
const N = 30;
const edge = (x0, y0, x1, y1) =>
	Array.from({ length: N }, (_, i) => {
		const t = i / N;
		return proj.invert([x0 + (x1-x0)*t, y0 + (y1-y0)*t]);
	});
const geoPts = [...edge(0,0,w,0), ...edge(w,0,w,h), ...edge(w,h,0,h), ...edge(0,h,0,0)];

6.6 その他のオーバーレイ

機能内容
夜側(night)太陽赤緯・経度から終端線を 31 点のポリゴンで計算、半透明の暗色で塗りつぶす
時計(clock)UTC を大きなフォントで表示。ズームアウト時(zoom < 2)のみ
座標表示(latlng)カーソル移動で緯度・経度・標高をリアルタイム更新
スケールバー(scale)log10 丸め + 単位自動選択(m/km 切り替え、metric/imperial 対応)
帰属表示(credit)各ベースマップのライセンス表記(attribution プロパティから)

7. Gint レイヤー — フル WebGL2 ベクター描画

gint.js Worker はユーザーが createRemoteLayer({ type:"gint" }) で生成する汎用レイヤーで、 GeoPBF 由来の Gint バイナリを受け取り、ライン・ポリゴン・ポイントを描画する。 hover picking・クリック・ハイライト・ポリゴン塗りつぶしをすべてサポートする。

7.1 モジュール分割

ファイル役割
gintState.js共有 GL 状態オブジェクト (s) の定義
gintPrograms.jsGLSL シェーダーのコンパイル・リンク・ユニフォーム取得
gintTextures.jsarcTex / metaTex / ptTex テクスチャ生成・削除
gintFBO.jsbaseFBO(クリーンシーン用)・pickFBO(ピッキング用)の生成・削除
gintRenderPasses.jsrenderCleanScene / drawOverlay / renderPickingBuffer の 3 パス
gintIdentify.jsGPU picking + JS ポリゴン内包判定、hover / leave ハンドラ

7.2 3 フレームバッファ構成

1
canvas(デフォルト FBO)— パン中のリアルタイム描画
drawing() イベントごとに直接描画。軽量・即時
↓ drawn() で確定
2
baseFBO — クリーンシーンのスナップショット
hover ハイライト解除時に blit して前フレームを復元。ハイライト往来のちらつきゼロ
↓ 同時に
3
pickFBO — Feature ID を RGB24 エンコード
視覚幅より太く描いてヒット感度を ~6 CSS px に拡大(pickMargin = 12 × dpr)

7.3 GPU Picking — RGB24 Feature ID

// ピッキング FBO にフィーチャー ID を RGB 24bit でエンコード
uint fid1 = meta.a + 1u;  // 0 = "ヒットなし" → +1 してずらす
v_color = vec4(
	float(fid1 & 255u) / 255.0,
	float((fid1 >> 8u) & 255u) / 255.0,
	float((fid1 >> 16u) & 255u) / 255.0,
	1.0
);

// readPixels でカーソル 1px を読み取り
gl.readPixels(pickX, pickY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, px);
const fid1 = px[0] | (px[1] << 8) | (px[2] << 16);
const featureId = fid1 === 0 ? null : fid1 - 1;

7.4 JS ポリゴン内包判定フォールバック

GPU picking がヒットしない(fid1 === 0)かつポリゴンデータが存在する場合、 カーソルの地理座標を Morton 整数座標に変換して findPolygon(geopbf)を呼ぶ。 縮小表示でグローブが小さく全コーナーが球体外になり lastViewBbox = null になる場合も動作する。

7.5 ハイライトの drawOverlay フロー

// activeId が変化したとき(hover 検出後)
// 1. baseFBO → canvas へ blit(クリーンシーンを復元)
gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);

// 2. アクティブ feature のエッジを太め+黄色で上書き(u_pass=1)
gl.uniform1f(uRender.u_line_width, lineWidth + 2.0);
gl.uniform1i(uRender.u_active_id,  activeId);

// 3. ポリゴン範囲が既知なら stencil でアクティブ外を dim
// (maskColor の alpha > 0 かつ polyEdgeByFid に範囲がある場合のみ)
主スレッド往復ゼロ

hover 検出 → drawOverlay の全フローが Worker 内で完結する。 postMessage("redraw") は使わず、readPixelsdrawOverlay を 同一 Worker 内で連続実行するため、主スレッドのラウンドトリップレイテンシが発生しない。

7.6 WebGL コンテキスト消失への対応

canvas.addEventListener("webglcontextlost", e => {
	e.preventDefault();
	// テクスチャ・FBO・プログラムの参照をすべてクリア
	s.arcTex = s.metaTex = s.ptTex = s.ptMetaTex = null;
	s.baseFBO = s.pickFBO = s.programs = null;
});
canvas.addEventListener("webglcontextrestored", () => {
	s.programs = createGintPrograms(s.gl);
	createFBOs(); uploadGintTextures();
	postMessage({ action: "redraw" });  // 主スレッドに再描画要求
});

8. 状態管理・ガジェット

8.1 IndexedDB による状態永続化

native-bucketCache(IndexedDB ラッパー)を使い、 ビュー状態とベースマップ名をセッション間で保持する。

map.stat = await Cache("GIS/stat");
map.baseName = await map.stat("base") || "osm.street";
map.view     = await map.stat("view") || [[135, 35, 0], 2];
// view = [[経度, 緯度, 回転角], ズーム]

// パン・ズーム確定後(drawn イベント)に自動保存
map.stat("view", getView());

8.2 標高取得(AltPBF 統合)

altpbfcreateGetHeight が返す関数を map.getHeight として登録する。 Move / Click イベントに alt フィールドが追加され、座標表示や標高断面に利用できる。

8.3 ガジェットシステム

UI コンポーネントは map.gadget(name, func) で登録するプラグイン方式で、 内蔵ガジェットとユーザー定義ガジェットを同等に扱える。 ガジェットは this = map として呼ばれる関数で、 map.addFrame で確保した DOM 領域に自由に UI を構築できる。

// 内蔵ガジェットの呼び出し
map.gadget.zoom();           // ズームボタンを leftTop に配置
map.gadget.layers();         // ベースマップ切り替えボタンを追加
const setTip = map.gadget.tip();   // カーソル追従 tip の制御関数を返す
setTip("クリックで詳細表示");     // tip テキストを設定

// ユーザー定義ガジェットの登録と呼び出し
map.gadget("myTool", function () {
	map.addFrame("rightTop");
	map.rightTop.append("div").text("Hello");
});
map.gadget.myTool();

フレーム配置位置

フレーム名位置主な用途
leftTop左上ズーム・方位・レイヤー切り替え等の操作ボタン
rightTop右上補助ボタン・ユーザー UI
leftBottom左下凡例
rightBottom右下補助情報
leftFrame地図左に固定パネルサイドメニュー(リサイズ対応)
rightFrame地図右に固定パネル属性パネル(リサイズ対応)
overlays地図上全面tip / pop / explain / loading など

内蔵ガジェット一覧 — 操作系(gadget1.js)

ガジェット説明
zoom() ズームイン(+)・アウト(−)ボタン。クリックごとに整数ズームレベルへスナップしながら map.mag() をアニメーション実行する
north() 現在の Z 軸回転角(地図の傾き)をボタンのアイコン内 SVG でリアルタイム表示し、クリックすると map.north() で北向きに戻す
layers() ベースマップ切り替えドロップダウン。map.Layers に登録されているレイヤー名を現在ロケールで表示し、選択すると map.setBase() を呼ぶ
leftPanel(opts)
rightPanel(opts)
サイドパネルの開閉を管理する。opts.active = true にすると地図エリアを実際に押し出すリサイズモード、 省略時は地図上に重なるモーダルモードで動作する。 開閉アニメーションは d3.easeCubic(変更可)で補間する。 戻り値はパネル内コンテンツエリアの D3 Selection
full() Fullscreen API を使ってフルスクリーン切り替え。フルスクリーン状態に応じてアイコンを自動切替する
constellation() 星座線・星座名の表示トグル。クリックすると Accessories Worker に toggle-constellations を送りメシエ天体表示も連動して切り替える
cpos() Geolocation API で現在地を取得し flyToFeature で移動する。 現在地はアニメーション SVG マーカー(パルス円)でオーバーレイ表示され、 地図を動かすと map.tester() で可視判定して自動的に表示/非表示を切り替える
shot() スクリーンショットをダウンロードする。 全 Canvas レイヤーを OffscreenCanvas に合成した後、 html2canvas でオーバーレイ(ボタン・noprint 要素を除く)を重ね、 WebP 形式でダウンロードする
print() 印刷用に 3 倍解像度でレンダリングし、新規ウィンドウで window.print() を実行する。 縦長・横長を自動判定して CSS で適切に配置する
measure() 距離・面積の計測モードに切り替えるトグルボタン。 有効時は Click イベントをキャンセルして createPolygon ツールを起動し、 クリックで頂点を追加しながらリアルタイムで距離・面積を表示する

内蔵ガジェット一覧 — 情報表示系(gadget2.js)

ガジェット説明
loading() LoadStart / LoadEnd イベントに連動してタイル読み込み中のインジケーターを表示する。 複数のタイルが同時に読み込まれる場合はすべての名前をリスト表示し、 すべて完了したら自動的に非表示になる
explain() 地図左上に説明テキストや HTML を表示するパネル。 返り値は setContent(html) 関数で、文字列・関数(D3 Selection を受け取る)のどちらも受け付ける。 opts.permanent = true にすると閉じるボタンを表示しない
legend() 地図左下に凡例を表示するパネル。クリックで折りたたみ、再展開ボタンで復元できる。 explain と同様に HTML または D3 関数でコンテンツを設定する
tip() カーソル位置に追従するツールチップ。 返り値の関数にテキストを渡すと表示、null を渡すと非表示になる。 画面端に近い場合は自動的に反対側に回り込む。 タッチデバイスではオフセットを広めにとる
pop() 地図上の特定地点に固定されたポップアップを作成する。 返り値の関数 pop(content, event) を呼ぶたびに新しいポップアップが生成される。 ポップアップから地点へ引き出し線(Canvas2D)を自動描画し、 ドラッグ移動・ピン固定(位置固定)が可能。pop.clear() で全消去
contextmenu() 右クリック(または長押し)で表示するコンテキストメニュー。 返り値の関数に [{ icon, name, func }] の配列を渡してメニュー項目を設定する
// pop の使用例
const pop = map.gadget.pop();
map.onClick(e => {
	if (!e) return;
	pop(`緯度: ${e.lat.toFixed(4)}<br>経度: ${e.lng.toFixed(4)}`, e);
});

// contextmenu の使用例
const setMenu = map.gadget.contextmenu();
setMenu([
	{ name: "この地点を中心に", func: map => map.flyToFeature({ type: "Point", coordinates: [map.center[0], map.center[1]] }) },
	{ name: "北に向ける",    func: map => map.north() },
]);
CSS テーマのカスタマイズ

map.setProperties() は CSS カスタムプロパティをドキュメントルートに書き込む。 設定できる主なプロパティ: spaceColor(宇宙背景色)、earthFilter(球体フィルター)、 borderColor(ボタン枠)、buttonSizefontSizefontFamily 等。


API サマリ

メソッド説明
map.setBase(name)ベースマップを切り替える(タイルキャッシュリセット含む)
map.setView(center, zoom, angle)即座にビュー変更
map.flyToFeature(feature, opts)d3.interpolateZoom アニメーションで移動
map.zoomToFeature(feature, opts)2 フェーズアニメーションで移動
map.bbox([x0,y0,x1,y1])バウンディングボックスへズーム / 現在の bbox 取得
map.mag(n, duration)現在スケールを n 倍にアニメーション
map.north(duration)Z 回転(傾き)をアニメーションで 0 に戻す
map.autoRotate(true/false)自動回転(d3.timer で 0.01°/ms)
map.tester([lng,lat])点が現在ビューポートに表示されているか確認
map.createLayer(opts)Canvas2D レイヤーを追加(GeoJSON 描画用)
map.createRemoteLayer(opts)Worker + OffscreenCanvas レイヤーを追加
ortho-map · GPL-3.0 · Kenji Yoshida · 2026