🥂

React × canvas-confetti 紙吹雪アプリ開発メモ

に公開

はじめに

Confetti Appは、ブラウザ上で動作するインタラクティブなコンフェッティ(紙吹雪)アニメーションアプリです。

ReactとTypeScriptを使って構築し、ユーザーが直感的に操作できるUIを作りました。canvas-confettiライブラリを使って、Reactによるコンポーネント設計を実践し、GitHub Pagesで公開しました。

🔗 GitHubリポジトリ
https://github.com/kkoisland/confetti-app

🌐 公開デモ
https://kkoisland.github.io/confetti-app

🛠 使用ライブラリ
https://www.npmjs.com/package/canvas-confetti

技術スタック

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:
https://kkoisland.github.io/confetti-app

ディレクトリ構造

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