gif-end-detector
Version:
A library for detecting GIF animation end events, based on libgif.js
229 lines (227 loc) • 7.9 kB
JavaScript
/**
* gifEndDetector - GIFアニメーション終了イベント検知ライブラリ
* libgif.jsをベースにしたシンプルなラッパー
*
* 依存: libgif.js (https://github.com/buzzfeed/libgif-js)
*/
/**
* GIFアニメーション終了検知ライブラリ
* @param source - GIFファイルのパスまたはURL
* @returns GifEndDetectorインスタンス
*/
function gifEndDetector(source) {
// インスタンス化パターンを強制する
if (!(this instanceof gifEndDetector)) {
return new gifEndDetector(source);
}
// libgif.jsが利用可能かチェック
if (typeof window === 'undefined' || !window.SuperGif) {
console.error('libgif.js (SuperGif) が見つかりません。先にロードしてください。');
this.source = source;
this._gif = null;
this._canvas = null;
this._totalFrames = 0;
this._currentFrame = 0;
this._isPlaying = false;
this._endCallbacks = [];
this._frameCallbacks = [];
this._loadCallbacks = [];
this._errorCallbacks = [];
this._onDrawFrame = null;
return this;
}
this.source = source;
this._gif = null;
this._canvas = null;
this._totalFrames = 0;
this._currentFrame = 0;
this._isPlaying = false;
this._endCallbacks = [];
this._frameCallbacks = [];
this._loadCallbacks = [];
this._errorCallbacks = [];
this._onDrawFrame = null;
return this;
}
// プロトタイプメソッド
gifEndDetector.prototype = {
/**
* GIFファイルを読み込み、準備完了後にコールバックを実行
* @param callback - 準備完了後に実行されるコールバック関数
* @returns チェーン用のインスタンス
*/
load: function (callback) {
var self = this;
if (callback && typeof callback === 'function') {
this._loadCallbacks.push(callback);
}
// libgif.jsのSuperGifを初期化
this._gif = new window.SuperGif({
src: this.source,
loop_mode: false,
auto_play: false,
on_end: function () {
// libgif.jsの終了イベント時に自分の終了コールバックを実行
self._handleEnd();
}
});
// GIFの読み込みを開始
this._gif.load(function () {
// 読み込み完了後の処理
self._canvas = self._gif.get_canvas();
self._totalFrames = self._gif.get_length();
// loadCallbacksを実行
self._loadCallbacks.forEach(function (cb) {
cb(self);
});
});
return this;
},
/**
* 終了イベントのコールバックを登録
* @param callback - 終了時に呼び出されるコールバック関数
* @returns チェーン用のインスタンス
*/
onEnd: function (callback) {
if (callback && typeof callback === 'function') {
this._endCallbacks.push(callback);
}
return this;
},
/**
* フレーム描画イベントのコールバックを登録
* @param callback - フレーム描画時に呼び出されるコールバック関数
* @returns チェーン用のインスタンス
*/
onFrame: function (callback) {
if (callback && typeof callback === 'function') {
this._frameCallbacks.push(callback);
}
return this;
},
/**
* エラー発生時のコールバックを登録
* @param callback - エラー時に呼び出されるコールバック関数
* @returns チェーン用のインスタンス
*/
onError: function (callback) {
if (callback && typeof callback === 'function') {
this._errorCallbacks.push(callback);
}
return this;
},
/**
* カスタムフレーム描画関数を設定
* @param drawFunction - カスタム描画関数
* @returns チェーン用のインスタンス
*/
setOnDrawFrame: function (drawFunction) {
if (typeof drawFunction === 'function') {
this._onDrawFrame = drawFunction;
// libgif.jsの描画関数をオーバーライド
if (this._gif) {
var self_1 = this;
var originalDrawFrame_1 = this._gif.drawFrame.bind(this._gif);
this._gif.drawFrame = function () {
// オリジナルの描画関数を実行
originalDrawFrame_1();
// 現在のフレーム番号を取得
var frameIndex = self_1._gif.getCurrentFrame();
self_1._currentFrame = frameIndex;
// カスタム描画関数を実行
if (self_1._canvas && self_1._onDrawFrame) {
var ctx = self_1._canvas.getContext('2d');
if (ctx) {
self_1._onDrawFrame(ctx, frameIndex, self_1._totalFrames);
}
}
// フレームコールバックを実行
self_1._frameCallbacks.forEach(function (cb) {
cb(frameIndex, self_1._totalFrames);
});
// 最後のフレームであれば終了処理
if (frameIndex === self_1._totalFrames - 1) {
self_1._handleEnd();
}
};
}
}
return this;
},
/**
* アニメーションを開始
* @returns チェーン用のインスタンス
*/
play: function () {
if (this._gif && !this._isPlaying) {
this._isPlaying = true;
this._gif.play();
}
return this;
},
/**
* アニメーションを停止
* @returns チェーン用のインスタンス
*/
pause: function () {
if (this._gif && this._isPlaying) {
this._isPlaying = false;
this._gif.pause();
}
return this;
},
/**
* アニメーションをリセット(最初のフレームに戻す)
* @returns チェーン用のインスタンス
*/
reset: function () {
if (this._gif) {
this._gif.move_to(0);
}
return this;
},
/**
* 特定のフレームに移動
* @param frameIndex - 移動先のフレーム番号
* @returns チェーン用のインスタンス
*/
moveToFrame: function (frameIndex) {
if (this._gif && frameIndex >= 0 && frameIndex < this._totalFrames) {
this._gif.move_to(frameIndex);
}
return this;
},
/**
* Canvas要素を取得
* @returns GIFが描画されているCanvas要素
*/
getCanvas: function () {
return this._canvas;
},
/**
* 総フレーム数を取得
* @returns GIFの総フレーム数
*/
getTotalFrames: function () {
return this._totalFrames;
},
/**
* 現在のフレーム番号を取得
* @returns 現在表示中のフレーム番号
*/
getCurrentFrame: function () {
return this._currentFrame;
},
/**
* 終了処理を実行する内部メソッド
* @private
*/
_handleEnd: function () {
this._isPlaying = false;
// 終了コールバックを実行
this._endCallbacks.forEach(function (cb) {
cb();
});
}
};
export { gifEndDetector as default };