みかづきブログ その3

本ブログは更新を終了しました。通算140万ユーザーの方に観覧頂くことができました。長い間、ありがとうございました。

👆

引越し先はこちらです!

YouTubeの埋め込みプレーヤーを管理するクラスをつくる

以前、 こんなクラス をつくりましたが、改良してみました。


続・YouTube Player APIをつかう - みかづきブログ その3


変更点

  • new できないように変更しました。
  • 自動再生するか否かをオプションで指定できるように変更しました。
  • オプションの引数をオブジェクトで渡すように変更しました。
  • buildメソッドを叩いた際にplay、stopを持ったコントローラーオブジェクトを返すよう変更しました。

JavaScript

(function(win, doc, ns) {

    "use strict";

    function EventDispatcher() {
        this._events = {};
    }

    EventDispatcher.prototype.hasEventListener = function(eventName) {
        return !!this._events[eventName];
    };

    EventDispatcher.prototype.addEventListener = function(eventName, callback) {
        if (this.hasEventListener(eventName)) {
            var events = this._events[eventName],
                length = events.length,
                i = 0;
    
            for (; i < length; i++) {
                if (events[i] === callback) {
                    return;
                }
            }

            events.push(callback);
        } else {
            this._events[eventName] = [callback];
        }
    };

    EventDispatcher.prototype.removeEventListener = function(eventName, callback) {
        if (!this.hasEventListener(eventName)) {
            return;
        } else {
            var events = this._events[eventName],
                i = events.length,
                index;
    
            while (i--) {
                if (events[i] === callback) {
                    index = i;
                }
            }
    
            events.splice(index, 1);
        }
    };

    EventDispatcher.prototype.fireEvent = function(eventName, opt_this, opt_arg) {
        if (!this.hasEventListener(eventName)) {
            return;
        } else {
            var events     = this._events[eventName],
                copyEvents = _copyArray(events),
                arg        = _copyArray(arguments),
                length     = events.length,
                i = 0;
    
            // eventNameとopt_thisを削除
            arg.splice(0, 2);
    
            for (; i < length; i++) {
                copyEvents[i].apply(opt_this || this, arg);
            }
        }
    
        function _copyArray(array) {
            var newArray = [],
                i = 0;
    
            try {
                newArray = [].slice.call(array);
            } catch(e) {
                for (; i < array.length; i++) {
                    newArray.push(array[i]);
                }
            }
    
            return newArray;
        }
    };

    function YTPlayer() {
        var _this = this,
            _player = null,
            isAutoStart = false;;

        EventDispatcher.call(this);

        _init();

        function _init() {
            var tag            = doc.createElement("script"),
                firstScriptTag = doc.getElementsByTagName("script")[0];

            tag.src = "https://www.youtube.com/iframe_api";
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

            function onYouTubeIframeAPIReady() {
                _this.fireEvent("YOUTUBE_READY");
            }

            // export
            win.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
        }

        function _onPlayerReady(evt) { // 動画再生準備完了時イベント
            var player = this.target;

            if (isAutoStart) {
                player.playVideo(); // 動画再生
            }
        }

        function _onPlayerStateChange(evt) { // 動画再生状態変更時イベント
            if (this.data === 0) { // 動画停止時
                _this.fireEvent("WATCHED_VIDEO", this.target, evt);
            }
        }

        /**
         * Playerを生成します
         * @param  {string}  id      // Player に置換する DOM の id属性(必須)
         * @param  {string}  videoId // YouTube の video ID(必須)
         * @param  {object}  opt_obj // オプション用のオブジェクト
         *         {number}  width       // プレイヤーの幅(省略時は640)
         *         {number}  height      // プレイヤーの高さ(省略時は480)
         *         {boolean} isAutoStart // 自動再生するか否か(省略時はfalse)
         */
        function build(id, videoId, opt_obj) {
            _player = new YT.Player(id, {
                    width   : (opt_obj && opt_obj.width)  || 640, // 動画幅
                    height  : (opt_obj && opt_obj.height) || 480, // 動画高さ
                    videoId : videoId,       // 動画ID
                    events  : {
                        onReady : function(player) {
                            _onPlayerReady.call(player, id);
                        },
                        onStateChange : function(player) {
                            _onPlayerStateChange.call(player, id);
                        }
                    },
                    playerVars: {
                        rel      : 0, // 関連動画
                        showinfo : 0, // 動画情報
                        controls : 1, // コントローラー
                        wmode    : "transparent" // z-indexを有効にする
                    }
                });

            isAutoStart = (opt_obj && opt_obj.isAutoStart) || false;

            return {
                play: play,
                stop: stop
            };
        }

        function play() {
            if (_player.playVideo) {
                _player.playVideo();
            } else {
                isAutoStart = true;
            }
        }

        function stop() {
            if (_player.stopVideo) {
                _player.stopVideo();
            }
        }

        this.build = build;
    }

    YTPlayer.originalConstructor   = YTPlayer.prototype.constructor;
    YTPlayer.prototype             = new EventDispatcher();
    YTPlayer.prototype.constructor = YTPlayer.originalConstructor;

    ns.YTPlayer = {
        getInstance : function() {
            if (!YTPlayer.instance) {
                YTPlayer.instance = new YTPlayer();
            }

            return YTPlayer.instance;
        }
    };

})(this, document, App);

つかいかた

(function(win, doc, ns) {
    
    "use strict";
    
    var youTube = ns.YTPlayer.getInstance();

    youTube.addEventListener("YOUTUBE_READY", function() {
        player = youTube.build("player", "1g0ebPju_eE");
    });

})(this, document, App);

DEMO


今回は以上です。