# gif-end-detector

GIFアニメーションの終了イベントを検知するための軽量ライブラリです。[libgif.js](https://github.com/buzzfeed/libgif-js)をベースにしており、GIFアニメーションの制御やフレーム単位での操作を可能にします。

## 特徴

- GIFアニメーションの**終了イベント検知**
- フレームごとの描画をカスタマイズ可能
- HTTP経由のGIFファイル読み込みサポート
- giflerに似た使用感と拡張機能
- TypeScript対応

## インストール

```bash
# npmを使用
npm install gif-end-detector

# yarnを使用
yarn add gif-end-detector
```

## 依存関係

このライブラリは以下のライブラリに依存しています：

- [libgif.js](https://github.com/buzzfeed/libgif-js) - GIFアニメーションの解析と描画

**重要**: libgif.jsはnpmパッケージとして提供されていないため、HTMLで直接読み込む必要があります。

## 基本的な使用方法

まず、HTMLにlibgif.jsを読み込みます（必須）：

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/libgif-js/3.0.3/libgif.js"></script>
```

### ブラウザ直接読み込み

```html
<!-- libgif.jsを先に読み込む -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/libgif-js/3.0.3/libgif.js"></script>
<!-- 次にgif-end-detectorを読み込む -->
<script src="https://unpkg.com/gif-end-detector@1.0.0/dist/gifEndDetector.js"></script>

<script>
  // GIFファイルのURL
  const gifUrl = 'path/to/animation.gif';

  // GIFを読み込む
  gifEndDetector(gifUrl).load(function(detector) {
    // Canvasを取得してDOMに追加
    const canvas = detector.getCanvas();
    document.getElementById('container').appendChild(canvas);
    
    // 終了イベントリスナーを追加
    detector.onEnd(function() {
      console.log('アニメーション終了！');
      // 終了時の処理
    });
    
    // アニメーション再生開始
    detector.play();
  });
</script>
```

### モジュールバンドラー使用時（webpack, Rollup, Vite等）

モジュールバンドラーを使用する場合でも、HTMLでlibgif.jsを読み込む必要があります。

```html
<!-- HTMLファイルでlibgif.jsを読み込む -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/libgif-js/3.0.3/libgif.js"></script>
```

```javascript
// JavaScriptファイル
import gifEndDetector from 'gif-end-detector';

// GIFファイルのURL
const gifUrl = 'path/to/animation.gif';

// GIFを読み込む
gifEndDetector(gifUrl).load(function(detector) {
  // 処理
});
```

## CDNの利用

CDNから直接ライブラリを使用することもできます：

```html
<!-- libgif.jsを先に読み込む -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/libgif-js/3.0.3/libgif.js"></script>

<!-- unpkgから -->
<script src="https://unpkg.com/gif-end-detector"></script>

<!-- または jsDelivrから -->
<script src="https://cdn.jsdelivr.net/npm/gif-end-detector"></script>
```

## 詳細なAPI

### `gifEndDetector(source)`

- `source` {String} - GIFファイルのパスまたはURL
- **戻り値**: {Object} - GifEndDetectorインスタンス

### メソッド

#### `load(callback)`

GIFファイルを読み込み、準備完了後にコールバックを実行します。

- `callback` {Function} - 準備完了後に実行されるコールバック関数
- **戻り値**: {Object} - チェーン用のインスタンス

#### `onEnd(callback)`

アニメーション終了時に実行されるコールバックを追加します。

- `callback` {Function} - 終了時に実行されるコールバック関数
- **戻り値**: {Object} - チェーン用のインスタンス

#### `onFrame(callback)`

フレーム描画時に実行されるコールバックを追加します。

- `callback` {Function} - フレーム描画時に実行されるコールバック関数
  - 引数: `frameIndex` {Number} - 現在のフレーム番号
  - 引数: `totalFrames` {Number} - 総フレーム数
- **戻り値**: {Object} - チェーン用のインスタンス

#### `onError(callback)`

エラー発生時に実行されるコールバックを追加します。

- `callback` {Function} - エラー時に実行されるコールバック関数
- **戻り値**: {Object} - チェーン用のインスタンス

#### `setOnDrawFrame(drawFunction)`

各フレームの描画処理をカスタマイズします。

- `drawFunction` {Function} - カスタム描画関数
  - 引数: `ctx` {CanvasRenderingContext2D} - Canvasのコンテキスト
  - 引数: `frameIndex` {Number} - 現在のフレーム番号
  - 引数: `totalFrames` {Number} - 総フレーム数
- **戻り値**: {Object} - チェーン用のインスタンス

#### `play()`

アニメーションを開始します。

- **戻り値**: {Object} - チェーン用のインスタンス

#### `pause()`

アニメーションを一時停止します。

- **戻り値**: {Object} - チェーン用のインスタンス

#### `reset()`

アニメーションを最初のフレームにリセットします。

- **戻り値**: {Object} - チェーン用のインスタンス

#### `moveToFrame(frameIndex)`

特定のフレームに移動します。

- `frameIndex` {Number} - 移動先のフレーム番号
- **戻り値**: {Object} - チェーン用のインスタンス

#### `getCanvas()`

GIFが描画されているCanvas要素を取得します。

- **戻り値**: {HTMLCanvasElement} - Canvas要素

#### `getTotalFrames()`

GIFの総フレーム数を取得します。

- **戻り値**: {Number} - 総フレーム数

#### `getCurrentFrame()`

現在表示中のフレーム番号を取得します。

- **戻り値**: {Number} - 現在のフレーム番号

## CORS対応

外部サーバーのGIFファイルにアクセスする場合、CORS制限にぶつかることがあります。以下の方法で対応できます：

```javascript
// Blobを経由してCORS制限を回避
fetch('https://example.com/animation.gif', { mode: 'cors' })
  .then(response => response.blob())
  .then(blob => {
    // BlobからローカルURLを作成
    const localUrl = URL.createObjectURL(blob);
    
    // gifEndDetectorでロード
    gifEndDetector(localUrl).load(function(detector) {
      // BlobURLを解放（重要）
      URL.revokeObjectURL(localUrl);
      
      // 以降、通常の使用方法と同じ
      detector.play();
    });
  });
```

## サンプル

`examples/`ディレクトリに様々な使用例があります：

- `example.html`: 基本的な使用例
- `gifler-style-example.html`: giflerに似たAPIの使用例
- `http-example.html`: HTTP経由でのGIF取得例
- `cors-proxy-example.html`: CORS制限回避の例
- `custom-example.html`: カスタム実装例

## ライセンス

MIT

## 謝辞

このライブラリは[libgif.js](https://github.com/buzzfeed/libgif-js)と[gifler](https://themadcreator.github.io/gifler/)にインスピレーションを受けています。
