React × canvas-confetti 紙吹雪アプリ開発メモ
はじめに
Confetti Appは、ブラウザ上で動作するインタラクティブなコンフェッティ(紙吹雪)アニメーションアプリです。
ReactとTypeScriptを使って構築し、ユーザーが直感的に操作できるUIを作りました。canvas-confettiライブラリを使って、Reactによるコンポーネント設計を実践し、GitHub Pagesで公開しました。
🔗 GitHubリポジトリ
🌐 公開デモ
🛠 使用ライブラリ
技術スタック
React (Functional Components)
Vite (開発環境とビルドツール)
TypeScript (型安全な開発)
Ant Design (UIコンポーネントライブラリ)
React Router (ページ遷移)
CSS Modules (モジュール化されたCSSによるスタイル管理)
ESLint (コードのリント)
Prettier (コードフォーマッター)
プロジェクトの進め方と開発の工夫
1つの.mdファイルで情報を一元管理:
設計やタスク、進捗、気づいたことをすべて1つのMarkdownファイルにまとめました。これによって、作業の流れを見返しやすくなり、この記事やスライドを作成するときにも役立ちました。
小さなブランチで目的別に作業:
うまくいかなかった実装にはブランチを切り、テーマやUIの調整、デプロイ設定などを分けて進めました。作業の整理がしやすくなり、切り戻しも簡単になりました。
開発環境のセットアップ手順
git@github.com:kkoisland/confetti-app.git
cd confetti-app
nvm use
npm install
npm run dev
実装した主な機能
Confettiランチャー:
ユーザーがスライダーで紙吹雪の量を調整し、ボタンで発射できる。
背景アニメーション:
マウスの動きやクリックに反応して、背景全体にコンフェッティを発生させる。
スクロールアニメーション:
ページスクロールするとエフェクトを自動的に表示し、ホバーで大きめのコンフェッティを発生させる。
インタラクティブギャラリー:
カラフルな丸をクリックすると、それぞれ異なるテーマのコンフェッティが表示される。
UI/UX設計とAnt Design導入
大きめなUIライブラリを使ってみたかったので、開発中の実験としてAnt Designを導入しました。ボタンやフォーム、タブなどの主要なUIコンポーネントをAnt Designで統一し、UIの一貫性を確認しています。
ダークモード・ライトモード対応
独自のカラースキームとAnt Designのカスタムテーマを使い、ダークモードとライトモードの切り替えを試みたものの、併用するのは難しく、最終的にはAnt Designのダークモードは使わずに実装することにしましたが、今後の改善余地はあります。
GitHub Pagesでの公開
GitHub Pagesを利用して、アプリケーションを公開しました。gh-pages ブランチからデプロイし、React Router は GitHub Pages と相性の良い HashRouter を採用しました。
公開URL:
ディレクトリ構造
ConfettiApp/
│
├── src/
│ ├── theme.ts
│ ├── components/ # 再利用可能なUIコンポーネント
│ │ ├── Header/
│ │ │ ├── Header.tsx
│ │ │ └── Header.module.css
│ │ ├── Footer/
│ │ │ ├── Footer.tsx
│ │ │ └── Footer.module.css
│ │ ├── ConfettiLauncher/
│ │ │ ├── ConfettiLauncher.tsx
│ │ │ └── ConfettiLauncher.module.css
│ │ ├── BackgroundAnimation/
│ │ │ ├── BackgroundAnimation.tsx
│ │ │ └── BackgroundAnimation.module.css
│ │ ├── ScrollAnimation/
│ │ │ ├── ScrollAnimation.tsx
│ │ │ └── ScrollAnimation.module.css
│ │ └── ConfettiGallery/
│ │ ├── ConfettiGallery.tsx
│ │ └── ConfettiGallery.module.css
│ │ ├── ConfettiEffects/ # Confettiエフェクトをまとめたフォルダ
│ │ │ ├── SnowConfetti.tsx # 雪のConfetti
│ │ │ ├── CherryBlossomConfetti.tsx # 桜のConfetti
│ │ │ ├── FreshLeavesConfetti.tsx # 若葉のConfetti
│ │ │ ├── FireworksConfetti.tsx # 花火のConfetti
│ │ │ ├── FallConfetti.tsx # 秋の葉のConfetti
│ │ │ └── ChristmasStarsConfetti.tsx # クリスマスの星のConfetti
│ │
│ ├── pages/ # 各ページのコンポーネントを追加
│ │ ├── ConfettiLauncherPage.tsx # Confettiランチャーのページ
│ │ ├── BackgroundAnimationPage.tsx # 背景アニメーションのページ
│ │ ├── ScrollAnimationPage.tsx # スクロールアニメーションのページ
│ │ └── ConfettiGalleryPage.tsx # インタラクティブなギャラリーのページ
│ │
│ ├── data/ # モックデータを管理するフォルダ
│ │ ├── confettiOptions.ts # Confettiの設定
│ │ ├── backgroundColors.ts # 背景色のリスト
│ │
│ ├── utils/ # ユーティリティ関数
│ │ └── colorUtils.ts
│ │
│ ├── App.tsx # アプリケーションのメインコンポーネント
│ ├── App.css
│ └── main.tsx # エントリポイント
│
├── package.json
└── tsconfig.json
コンポーネント構成図
App.tsx
├── Header.tsx
├── Footer.tsx
└── Routes
├── ConfettiLauncherPage.tsx
│ └── ConfettiLauncher.tsx
├── BackgroundAnimationPage.tsx
│ └── BackgroundAnimation.tsx
├── ScrollAnimationPage.tsx
│ └── ScrollAnimation.tsx
└── ConfettiGalleryPage.tsx
└── ConfettiGallery.tsx
└── ConfettiEffects
├── SnowConfetti.tsx
├── CherryBlossomConfetti.tsx
├── FreshLeavesConfetti.tsx
├── FireworksConfetti.tsx
├── FallConfetti.tsx
└── ChristmasStarsConfetti.tsx
状態管理の方針
すべての State はローカル(useState)で管理
グローバル状態管理(ReduxやJotai)は今回は導入していない
必要に応じて、今後グローバル状態や Context API を検討
やり残し・今後の改善
Confettiエフェクトのパラメーター整理と共有:
ギャラリーで使用した各コンフェッティエフェクトのパラメーターを整理し、他の開発者が簡単にコピペして使えるサンプルコードとしてまとめたかった。
レスポンシブ対応:
現状はPC表示前提のレイアウトになっているため、モバイルやタブレットでも快適に操作できるように調整する。
MITライセンス導入:
ライセンスを明示して、オープンソースとしての整備を行う予定。
学びと気づき
状態管理の学び:
状態はすべて useState によるローカル管理とした。Jotai や Redux、Context API などのグローバルステート管理も検討したが、ルーティングやコンポーネント設計との相性が難しく、今回は採用を見送った。今後はより適切な設計を考えた上で、グローバルな状態管理を再検討したい。
Ant Designの活用と制限:
UIの統一が簡単になり、デザインの一貫性を保つことはできた。ただし、カスタムテーマやダークモードの切り替えは想像以上に複雑で、プロジェクト独自のデザインと両立させるのは難しかった。結果として、Ant Designのダークモードは使用せず、シンプルな実装に戻した。
まとめ
最初は自分の学びの場として立ち上げ、いろいろな実験をしたいと思って始めたプロジェクトでしたが、自分だけのプロジェクトであっても「完成させること」の大切さを感じるようになりました。途中で、できることとできないことを切り分け、きちんと終わらせる方向に転換。その結果が、今回公開したこのConfetti Appです。
Discussion