スマートグラス研究所 SMART GLASS LAB / TOKYO, JP Contact Us →

開発ノウハウ 読了 約15分

HTML/CSS/JSだけでグラスアプリが作れる
——Meta Ray-Ban Display「Web Apps」で使えるAPI徹底ガイド

Meta Ray-Ban Display(MRBD)には、HTML/CSS/JavaScriptだけで動く「Web Apps」という開発パスが用意されています。専用フレームワークもネイティブSDKも不要で、普通のWeb技術だけで「グラスの中で動くアプリ」を作れるのが最大の魅力です。

この記事では、Meta公式の開発者ドキュメント「Build」ページ(2026年6月22日更新版)を読み込み、Webアプリからアクセスできる機能——ディスプレイ、ニューラルバンド入力、加速度・ジャイロ・コンパス(IMU)、位置情報、ローカルストレージなど——を、パラメータの単位・値の範囲・デフォルト値まで踏み込んで日本語でまとめます。

NOTE

Web Appsは現在デベロッパープレビュー段階です。仕様は今後変更される可能性があるため、最新情報は文末の公式ドキュメントで確認してください。

1. Web Appsとは? 全体像を30秒で

Web Appsは、標準のHTML/CSS/JavaScriptで書いたWebアプリを、グラス内蔵ディスプレイ上に直接レンダリングする仕組みです。W3C標準のWeb APIがそのまま使えるので、スマホ向けWebアプリを作ったことがあれば知識をほぼ流用できます。スマホ側にコンパニオンアプリを用意する必要がない点が、ネイティブSDK(Meta Wearables Device Access Toolkit)との大きな違いです。

現在、Webアプリからアクセスできるのは次の6つです。

  • ディスプレイ:600×600pxの加算型(additive)ディスプレイ
  • 入力:ニューラルバンド+テンプル(つる)のタッチ操作 → 矢印キー/Enterイベントに変換
  • センサー(IMU):加速度・ジャイロ・コンパス
  • 位置情報:ペアリングしたスマホ経由のGPS
  • ローカルストレージ:localStorage / sessionStorage(各5MB)
  • アプリアイコン

逆に、現時点で使えない機能は以下のとおりです。

  • カメラ
  • マイク
  • テキスト入力
  • オフライン対応
  • 通知
  • 戻るナビゲーション(Back Navigation)

また、マウスカーソルのような連続的なカーソル操作もありません。

つまり現時点のWeb Appsは、「見る・選ぶ・頭を動かす・現在地を知る」に特化したプラットフォームと捉えるのが正確です。音声や撮影を使いたい場合はネイティブSDK側(Device Access Toolkit)の領域になります。

2. ディスプレイ:黒は「透明」になる

MRBDのディスプレイは加算型の導波路(additive waveguide)方式で、現実の風景の上に光を「足す」ことで映像を表示します。この仕組みが、UIデザインに直接影響します。

  • 純粋な黒(#000000)のピクセルは光を一切発しない=完全に透明になる
  • 明るく鮮やかな色ほど、現実の風景の上に光が加算されてよく見える

推奨されるデザイン

  • 背景はダーク系に。実質透明になるため視界を遮らない。逆に明るい背景はグレア(眩しさ)の原因になり、可読性が落ちる
  • テキストやインタラクティブ要素には明るく高コントラストな色を使う。アクセントにはビビッドカラー
  • フォントサイズは本文16px以上、主要コンテンツは20〜24pxが目安

ビューポートは600×600px固定・スクロール禁止

すべてのコンテンツは600×600pxの固定ビューポート内に収め、スクロールは避けます。ズームを防ぐviewportメタタグと、はみ出しを防ぐCSSをセットで入れておくのが定石です。

<meta name="viewport" content="width=600, height=600, initial-scale=1.0, user-scalable=no">
body {
  width: 600px;
  height: 600px;
  overflow: hidden; /* ビューポート外へのはみ出しを防ぐ */
}

3. 入力:ニューラルバンドは「矢印キー+Enter」としてアプリに届く

MRBDのUI操作は2系統あります。

  • ニューラルバンド:手首に装着するリストバンド。指のジェスチャーで操作
  • キャプタッチ:テンプル(つる)部分に内蔵されたタッチストリップ。スワイプを検出

開発者にとって重要なのは、これらのジェスチャーがグラスOS側で標準のキーボードイベントに変換されてWebアプリに配信されるという点です。

  • 方向操作 → ArrowUp / ArrowDown / ArrowLeft / ArrowRight
  • 決定 → Enter

公式のサンプルコードでは、これに加えて Escape を「戻る」(history.back())として扱う実装パターンが示されています。

マウス・タッチスクリーン・物理キーボードは存在しないため、すべてのインタラクティブ要素を、方向移動+Enterだけで到達・実行できるように設計する必要があります。

実装パターン:.focusableクラスとフォーカス管理

インタラクティブ要素に.focusableクラスを付け、矢印キーでフォーカスを巡回させるのが公式推奨のパターンです。

<button class="focusable">スタート</button>
<button class="focusable">設定</button>
// 矢印キーでフォーカスを移動し、Enterで実行する最小構成
document.addEventListener('keydown', (e) => {
  const items = [...document.querySelectorAll('.focusable:not([disabled])')];
  if (!items.length) return;
  const i = items.indexOf(document.activeElement);

  switch (e.key) {
    case 'ArrowUp':
    case 'ArrowLeft':
      items[(i - 1 + items.length) % items.length].focus();
      break;
    case 'ArrowDown':
    case 'ArrowRight':
      items[(i + 1) % items.length].focus();
      break;
    case 'Enter':
      document.activeElement.click();
      break;
    case 'Escape':
      history.back(); // 「戻る」の実装例
      break;
    default:
      return; // 扱わないキーはpreventDefaultしない
  }
  e.preventDefault();
});
.focusable {
  min-height: 88px;              /* グラス上の最小タップターゲット */
  border: 2px solid transparent;
  transition: all 150ms ease;
}
.focusable:focus {
  outline: none;
  border-color: #00d4ff;         /* フォーカス位置がひと目で分かるように */
}

押さえておきたい数値・ルール:

  • 最小タップターゲット(フォーカス対象の高さ)は88px
  • フォーカス状態は必ず視覚的に分かるようにする(ボーダー、グローなど)
  • 非表示・無効化した要素はフォーカス対象から除外する

4. センサー(IMU):加速度・ジャイロ・コンパス

グラス本体のIMU(慣性計測ユニット)には、W3C標準のDeviceMotionEventとDeviceOrientationEventでアクセスできます。スマホブラウザとまったく同じ書き方で、windowにイベントリスナーを追加するだけです。

4-1. パーミッション(許可)の取り方

モーション・方位データの利用にはユーザーの明示的な許可が必要です。ポイントは3つ。

  • 許可リクエストはユーザージェスチャー(ボタン押下など)から呼び出す必要がある。ページ読み込み時の自動呼び出しは不可
  • クロスプラットフォーム互換のため、DeviceOrientationEvent.requestPermission()が存在するかチェックしてから呼ぶ(iOS Safari系ではこの関数が存在する)
  • グラスのランタイムおよび多くのAndroidブラウザでは自動的に許可される
function startIMU() {
  window.addEventListener('deviceorientation', onOrientation);
  window.addEventListener('devicemotion', onMotion);
}

if (typeof DeviceOrientationEvent !== 'undefined' &&
    typeof DeviceOrientationEvent.requestPermission === 'function') {
  // 明示的な許可が必要な環境(iOS Safariなど)
  DeviceOrientationEvent.requestPermission().then((state) => {
    if (state === 'granted') startIMU();
  });
} else {
  // グラスのランタイムや多くのAndroidブラウザは自動で許可される
  startIMU();
}

4-2. DeviceMotionEvent:加速度+回転速度(ジャイロ)

リアルタイムの加速度と角速度が取れます。動きの検出、G(重力加速度)の計測、回転スピードの追跡などに使います。

取得できるパラメータ

  • accelerationIncludingGravity.x / .y / .z — 重力を含む加速度。単位:m/s²
  • rotationRate.alpha — ヨー方向(首を左右に振る)の回転速度。単位:度/秒(deg/s)
  • rotationRate.beta — ピッチ方向(うなずく)の回転速度。単位:度/秒
  • rotationRate.gamma — ロール方向(首をかしげる)の回転速度。単位:度/秒
window.addEventListener('devicemotion', (e) => {
  // 加速度(重力込み)[m/s²]
  const { x, y, z } = e.accelerationIncludingGravity;

  // 合成加速度をG値に換算(9.81 m/s² = 1G)
  const g = Math.sqrt(x * x + y * y + z * z) / 9.81;

  // ジャイロ:回転速度 [deg/s]
  const yawRate   = e.rotationRate.alpha; // ヨー
  const pitchRate = e.rotationRate.beta;  // ピッチ
  const rollRate  = e.rotationRate.gamma; // ロール
});

4-3. DeviceOrientationEvent:方位・チルト・ロール

地球に対するグラスの「現在の向き」が取れます。コンパス方位の表示、チルト検出、空間的なUIなどに使えます。

取得できるパラメータ(値の範囲つき)

  • alpha — コンパス方位(z軸まわりの回転):0〜360°
  • beta — 前後のチルト(x軸まわりの回転):-180〜180°
  • gamma — 左右のチルト(y軸まわりの回転):-90〜90°
window.addEventListener('deviceorientation', (e) => {
  const heading = e.alpha; // 方位角 0–360°
  const tilt    = e.beta;  // 前後チルト -180〜180°
  const roll    = e.gamma; // 左右チルト -90〜90°
});

グラスの場合、頭の向きがそのままセンサー値になるのが面白いところです。「見ている方角に応じた情報表示」「顔の傾きで操作するゲーム」などが、このAPIだけで作れます。

4-4. センサー利用のベストプラクティス

公式ドキュメントでは推奨・非推奨が明確に示されています。

推奨(Consider)

  • 許可リクエストはユーザージェスチャー(ボタン押下など)から行う
  • リスナーを追加する前にAPIの存在をチェックする
  • 高頻度のセンサー更新は、スロットリング/デバウンスしてからUIに反映する
  • チルト系のインタラクションにはaccelerationIncludingGravityを使う
  • センサーデータが不要になったらイベントリスナーを解除する

非推奨(Avoid)

  • ページロード時にrequestPermission()を自動で呼ぶ
  • DeviceOrientationEventが常に定義されている前提で書く
  • センサーイベントのたびに毎回DOMを更新する
  • 重力の文脈が必要な場面で(重力抜きの)加速度だけに頼る
  • バックグラウンドでリスナーを放置する(バッテリーを消耗する)

5. 位置情報:グラス自体にGPSはない。「スマホ経由」で取る

MRBDは標準のnavigator.geolocation APIを実装していますが、グラス本体には測位センサーがなく、位置情報はペアリングしたスマホ(コンパニオンデバイス)から取得されます。書き方は普通のWebアプリと完全に同じです。センサー同様、ユーザーの許可が必要です。

5-1. 単発取得:getCurrentPosition

position.coordsで取得できるパラメータ(単位つき)

  • latitude — 緯度。10進法の度(decimal degrees)
  • longitude — 経度。10進法の度
  • accuracy — 精度。単位:m
  • altitude — 高度。単位:m(nullの場合あり)
  • speed — 速度。単位:m/s(nullの場合あり)
  • heading — 進行方位。北からの度数(nullの場合あり)
  • position.timestamp — 取得時刻。エポックからのミリ秒(UTC)
navigator.geolocation.getCurrentPosition(
  (position) => {
    const c = position.coords;
    console.log(c.latitude, c.longitude); // 緯度・経度(10進度)
    console.log(c.accuracy);              // 精度 [m]
    console.log(c.altitude);              // 高度 [m](null可)
    console.log(c.speed);                 // 速度 [m/s](null可)
    console.log(c.heading);               // 方位 [°](null可)
    console.log(position.timestamp);      // エポックms(UTC)
  },
  (error) => {
    console.error(error.code, error.message);
  },
  { timeout: 15000 }
);

5-2. 連続トラッキング:watchPosition / clearWatch

移動に合わせて継続的に位置を受け取るにはwatchPositionを使います。

const watchId = navigator.geolocation.watchPosition(
  (position) => {
    // 位置が更新されるたびに呼ばれる
  },
  (error) => {
    console.error(error.code, error.message);
  }
);

// 不要になったら必ず停止する
navigator.geolocation.clearWatch(watchId);

5-3. オプション(第3引数)の詳細

getCurrentPositionとwatchPositionは、どちらも第3引数でオプションを取ります。

  • enableHighAccuracy — boolean/デフォルト:false。可能な限り高精度の位置を要求する。取得に時間がかかり、消費電力が増える可能性がある
  • timeout — number(ミリ秒)/デフォルト:Infinity。位置取得を待つ最大時間。実用上は10000〜15000ms(10〜15秒)が推奨値
  • maximumAge — number(ミリ秒)/デフォルト:0。この値より新しいキャッシュ済みの位置であれば受け入れる
navigator.geolocation.getCurrentPosition(onSuccess, onError, {
  enableHighAccuracy: true, // 高精度を要求(デフォルト false)
  timeout: 15000,           // 最大待ち時間 ms(デフォルト Infinity)
  maximumAge: 5000          // これより新しいキャッシュは許容 ms(デフォルト 0)
});

5-4. エラーコード

エラーコールバックは必ず用意しましょう。エラーは3種類です。

  • 1 = PERMISSION_DENIED — 装着者が許可リクエストを拒否した
  • 2 = POSITION_UNAVAILABLE — 位置を取得できなかった(例:スマホがオフライン)
  • 3 = TIMEOUT — 指定したtimeoutを超過した

5-5. 精度と実運用上の注意

  • 位置情報の出どころは、ペアリングされたスマホのGPS/ネットワーク測位
  • 期待できる精度は5〜50m(電波状況に依存)
  • 初回リクエストは数秒かかることがあるため、timeoutは10〜15秒に設定しておく
  • 許可リクエストはユーザージェスチャーから行う

6. ローカルストレージ:各5MBまで

標準のWeb Storage APIがそのまま使えます。

  • localStorage — 上限5MB。セッションをまたいで永続化(アプリを閉じて再度開いても残る)
  • sessionStorage — 上限5MB。現在のセッション限り(セッション終了で消える)
  • どちらも文字列のkey-valueストア。構造化データはJSONにして保存する
// 保存・読み出し・削除
localStorage.setItem('userPreference', 'dark');
const pref = localStorage.getItem('userPreference'); // 'dark'(なければ null)
localStorage.removeItem('userPreference');
localStorage.clear(); // 全削除

// 構造化データはJSONで
localStorage.setItem('score', JSON.stringify({ best: 1200, plays: 8 }));
const score = JSON.parse(localStorage.getItem('score') || '{}');

用途は、ユーザー設定・小さなキャッシュ・アプリの状態保存などの軽量データ向けです。大きなblobや画像、数MB級のデータセットの保存は避けます。

7. アプリアイコン

  • Unicode記号、または52×52pxを超える高解像度PNGファビコンを使う
  • システムはWeb Appマニフェストとページソースをチェックする(favicon.icoだけを見るわけではない)
  • 適切なアイコンが見つからない場合は、デフォルトのフォールバックアイコンが表示される
  • SVGは非対応

HTMLの<link>タグで指定する方法:

<link rel="icon" href="/icon-96.png" sizes="96x96">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">

Web Appマニフェストで指定する方法(各エントリにsrcとsizesが必要):

<link rel="manifest" href="/manifest.webmanifest">
{
  "icons": [
    { "src": "/icons/icon-96.png", "sizes": "96x96" },
    { "src": "/icons/icon-192.png", "sizes": "192x192" }
  ]
}

8. 忘れずに入れたいHTMLメタデータ

<head>に以下の2つを追加しておくと、今後登場するディスカバリー面(アプリ発見機能)への対応と、「このサイトはMRBD非対応です」とユーザーに知らせる仕組みへの対応ができます。

<head>
  <!-- アプリの簡単な説明 -->
  <meta name="description" content="アプリの説明文">
  <!-- MRBD対応Webアプリであることを宣言 -->
  <meta name="mrbd-web-app-capable" content="yes">
</head>

9. おまけ:公式が「AIコーディング推し」を明言している

公式ドキュメントには「Web Appsを作る最も簡単な方法はAIコーディングツールを使うこと」と明記されています。具体的には次の構成が最も確実とされています。

  • Replit、Manus、Lovable、Claude Code、Vercel、CursorなどのAIコーディングツール/プラットフォーム
  • 公式GitHubプラグイン(facebookincubator/meta-wearables-webapp)
  • Wearables MCPエンドポイント https://mcp.developer.meta.com/wearables の search_webapps_docs ツールで、最新ドキュメントをAIに検索させる

公式が用意しているスタータープロンプトも、「600×600px固定・スクロールなし・ダーク背景・矢印キー+Enter操作・全要素フォーカス可能」という制約をAIに伝える内容になっています。

10. まとめ:センサー×位置情報が「グラスらしさ」の入口

最後に、できること・できないことを整理します。

  1. フル活用できるもの — 頭の動き:加速度(m/s²)・回転速度(deg/s)・方位/チルト(度)。現在地:緯度経度・精度・高度・速度・進行方位(スマホ経由、精度5〜50m)。永続化:localStorage/sessionStorage 各5MB
  2. まだ使えないもの — カメラ・マイク・テキスト入力・オフライン・通知・戻るナビゲーション
  3. UIの大前提 — 600×600px固定・スクロールなし・ダーク背景・矢印キー+Enterのみ・全要素フォーカス可能

応用アイデアの例

  • コンパス方位(alpha)を使った方角ナビ・方位クイズ
  • チルト(beta / gamma)を使った「首かしげ操作」ゲーム
  • watchPositionを使った散歩ログや速度計(speedはm/sなので、×3.6でkm/hに換算)
  • localStorageでハイスコアや設定を永続化

600×600px・矢印キー+Enter・ダーク背景という強い制約はありますが、裏を返せば「頭の向き」と「現在地」という、スマホにはない入力を標準Web APIだけで扱えるプラットフォームです。Webの知識がそのまま活きるので、参入障壁はかなり低いと感じています。

出典・参考リンク

本記事は上記公式ドキュメントを筆者が読み解き、日本語で再構成したものです。Web Appsはデベロッパープレビュー段階のため、仕様は変更される可能性があります。