2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Looker Extensionでルーレットアプリ作ってみた

Last updated at Posted at 2025-12-20

本記事は ZOZO Advent Calendar 2025 シリーズ 2 の 21 日目の記事です。

概要

先日のLooker User Meetupで、@mashiike さんが「コーディングエージェントに独自Extension書かせてみた」という発表をされていました。

Looker Extensionは通常のReactアプリとは異なり、サンドボックス化されたiframe内で動作するため、AIに書かせるにも工夫が必要とのこと。この発表を聞いて「自分も何か作ってみたい」と思いました。
何を作ろうか考えた結果、ダッシュボードを複数人で見る時にファシリをルーレットで決めたいことあるよね!という安直な発想で、コーディングエージェント(Claude Code)と一緒にルーレットアプリを作ることにしました。

本記事では、開発の流れと、一番ハマった結果判定ロジックのバグ解消について紹介します。

デモ

早速、完成したルーレットをお見せします。

demo-roulette.gif

「ダンボー」と「フルくん」は誰やねん...?となりましたが、これはZOZOTOWNでおなじみのキャラクターとして生成AIが追加していました。選択肢は自由に編集できるので、実際に使う際はチームメンバーの名前などに変更できます。

開発の流れ

プロジェクト構成の生成

最初に「ルーレットアプリを作りたい」と伝えると、Claude Codeが以下のファイルを生成してくれました。

  • roulette-app/src/components/RouletteWheel.tsx - ルーレット本体
  • roulette-app/src/App.tsx - メインコンポーネント
  • roulette-app/src/index.tsx - エントリーポイント
  • roulette-app/src/index.css - CSSスタイル
  • roulette-app/package.json - 依存関係
  • roulette-app/webpack.config.js - ビルド設定
  • roulette-app/tsconfig.json - TypeScript設定
  • manifest.lkml への追記

SVGで円弧を描画する部分、CSS transitionでアニメーションさせる部分など、基本的な実装はすべてコーディングエージェントが書いてくれました。

ハマったポイント:結果判定ロジック

ただし、一発で完璧に動いたわけではありません。
特に修正する必要があったのは結果判定のロジックでした。ルーレットが止まった後、「ポインターが指しているセグメントと表示される結果が一致しない」という問題が発生しました。例えば、ポインターが「フルくん」を指しているのに「ZOZO太郎」と表示されてしまいます。

問題の原因

最初のコードはこうでした。

const selectedIndex = Math.floor((totalRotation % 360) / segmentAngle);

これだと、ホイールの回転方向とポインターの位置関係が考慮されていません。

修正後のロジック

何度かやり取りを重ねて、以下のロジックに修正しました。

const segmentAngle = 360 / options.length;
const normalizedRotation = totalRotation % 360;
const pointerPosition = (360 - normalizedRotation + 360) % 360;
const selectedIndex = Math.floor(pointerPosition / segmentAngle) % options.length;

ポイントは 360 - normalizedRotation の部分です。

  • ポインターは上(0度の位置)に固定
  • ホイールが時計回りに回転
  • ホイールが72度回転すると、ポインターから見ると反時計回りに72度移動したように見える

つまり、ホイールの回転方向を反転させる必要がありました。

Looker Extensionとしての設定

manifest.lkmlでダッシュボードタイルとして使えるように設定します。

application: roulette_app {
  label: "Looker Roulette"
  file: "roulette-app/dist/roulette_app.js"
  mount_points: {
    standalone: yes
    dashboard_tile: yes
  }
  entitlements: {
    local_storage: yes
  }
}

dashboard_tile: yesを設定することで、ダッシュボードに埋め込むことができます。

まとめ

コーディングエージェントを使うことで、Looker Extensionの開発がかなり楽になりました。実際に1〜2時間ほどで作成することができました。SVGの描画やアニメーションなど、自分で一から書くと時間がかかる部分をお任せできます。

ただし、ロジックの細かい部分はやはり人間が検証する必要があります。今回の結果判定のように「動いているように見えて実は間違っている」パターンは、コーディングエージェントだけでは気づきにくいです。

Looker Extension特有の制約(サンドボックス化されたiframe)を理解した上で、AIと協力して開発するのが良いアプローチだと感じました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?