2

YouTube iFrame API を使用して、多数の動画をページに埋め込んでいます。ドキュメントはこちら: https://developers.google.com/youtube/iframe_api_reference#Requirements

要約すると、次のスニペットを使用して API を非同期的にロードします。

 var tag = document.createElement('script');
 tag.src = "http://www.youtube.com/player_api";
 var firstScriptTag = document.getElementsByTagName('script')[0];
 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

読み込まれると、API は定義済みのコールバック関数を起動しますonYouTubePlayerAPIReady

追加のコンテキスト: Google Closure でこのライブラリ ファイルを定義しています。私は名前空間を提供しています:goog.provide('yt.video');

次にgoog.exportSymbol、API が関数を見つけられるように使用します。それはすべてうまくいきます。

私の課題は、2 つの変数をコールバック関数に渡したいということです。windowオブジェクトのコンテキストでこれら 2 つの変数を定義せずにこれを行う方法はありますか?

goog.provide('yt.video');

goog.require('goog.dom');

yt.video = function(videos, locales) {
  this.videos = videos;
  this.captionLocales = locales;

  this.init();
};

yt.video.prototype.init = function() {
  var tag = document.createElement('script');
  tag.src = "http://www.youtube.com/player_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
};

/*
 * Callback function fired when YT API is ready
 * This is exported using goog.exportSymbol in another file and
 * is being fired by the API properly.
 */
 yt.video.prototype.onPlayerReady = function(videos, locales) {
    window.console.log('this :' + this); //logs window
    window.console.log('this.videos : ' + this.videos); //logs undefined
    /*
     * Video settings from Django variable
     */
    for(i=0; i<this.videos.length; i++) {
      var playerEvents = {};
      var embedVars = {};

      var el = this.videos[i].el;
      var playerVid = this.videos[i].vid;
      var playerWidth = this.videos[i].width;
      var playerHeight = this.videos[i].height;
      var captionLocales = this.videos[i].locales;
      if(this.videos[i].playerVars)
        var embedVars = this.videos[i].playerVars;
      }
      if(this.videos[i].events) {
        var playerEvents = this.videos[i].events;
      }

      /*
       * Show captions by default
       */
      if(goog.array.indexOf(captionLocales, 'es') >= 0) {
        embedVars.cc_load_policy = 1;
      };

      new YT.Player(el, {
        height: playerHeight,
        width: playerWidth,
        videoId: playerVid,
        events: playerEvents,
        playerVars: embedVars
    });
 };

};

これを初期化するために、現在、自己実行匿名関数内で次を使用しています。

  var videos = [
    {"vid": "video_id", "el": "player-1", "width": 640, "height": 390, "locales": ["es", "fr"], "events": {"onStateChange": stateChanged}}, 
    {"vid": "video_id", "el": "player-2", "locales": ["es", "fr"], "width": 640, "height": 390}
  ];

  var locales = ['es'];

  var videoTemplate = new yt.video(videos, locales);
4

2 に答える 2

2

onYouTubePlayerAPIReadyAPI が期待するようにグローバル関数として定義し、onPlayerReadyその関数内からメソッドを呼び出すのはどうですか? コードサンプル:

window.onYouTubePlayerAPIReady = function () {
    var args = Array.prototype.slice.call(arguments);
    args.push(videos, locales);
    videoTemplate.onPlayerReady.apply(videoTemplate, args);
};

そして、 onPlayerReady メソッドの署名を変更して、同じ順序で引数を受け入れるようにします

于 2012-06-11T03:54:49.030 に答える
1

あなたの特定の質問に答えるには:

私の課題は、2つの変数をコールバック関数に渡したいということです。ウィンドウオブジェクトのコンテキストでこれらの2つの変数を定義せずにこれを行う方法はありますか?

はい、グローバル変数を使用せずにコールバック関数にデータを提供する方法があります。ただし、コールバック関数を確認する前に、YouTubeAPIには次の要件があります。

さらに、YouTubeプレーヤーを含むHTMLページには、という名前のJavaScript関数を実装する必要がありますonYouTubePlayerReady。プレーヤーが完全に読み込まれ、APIが呼び出しを受信する準備ができると、APIはこの関数を呼び出します。

YouTube APIのでは、次のように関数内にイベントリスナーを追加onYouTubePlayerReadyします。

function onYouTubePlayerAPIReady() {
  var player;
  player = new YT.Player('player', {
    width: 1280,
    height: 720,
    videoId: 'u1zgFlCw8Aw',
    events: {
      'onReady': onPlayerReady,
      'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
      'onStateChange': onPlayerStateChange,
      'onError': onPlayerError
    }
  });
} 

サンプルのコールバック関数は、YouTubeオブジェクトによって発行されたyt.video.prototype.onPlayerReadyYouTubeAPIイベントのイベントリスナーを対象としているようです。APIドキュメントには、オブジェクトを構築するときにイベントリスナーが追加されるか、関数を使用して追加されることが示されています(Closure Libraryの代替はです)。onReadyYT.PlayerYT.PlayeraddEventListenergoog.events.listen

イベントリスナーはYouTubeオブジェクトから発行されyt.video.prototype.onPlayerReadyたイベントを「リッスン」する必要があるため、インスタンスによって発行されたイベントをリッスンすることを目的としたイベントリスナー内に新しいインスタンスを構築することは循環的です。onReadyYT.PlayerYT.Playeryt.video.prototype.onPlayerReadyYT.Player

グローバル変数を使用せずにコールバック関数にデータを提供するという元の質問に戻ると、イベントリスナーに任意の関数引数を渡すことはできません(たとえば、上記の元のコードサンプルでは、​​配列ではなくオブジェクトを最初の引数としてyt.video.prototype.onPlayerReady受け入れる必要があります)。ただし、イベントリスナーはコールバック関数として使用でき、のインスタンスにバインドされている限り、インスタンスオブジェクトの状態にアクセスできます。Eventvideosyt.video.prototype.onPlayerReadyyt.videoyt.video

this引数を特定のオブジェクトにバインドする1つの方法は、クロージャーライブラリ関数goog.bind(functionToCall、selfObject、var_args)を使用することです。コンストラクターは次のyt.videoように変更できます。

goog.provide('yt.video');

goog.require('goog.dom');

/**
 * @constructor
 */
yt.video = function(videos, locales) {
  this.videos = videos;
  this.captionLocales = locales;

  this.onPlayerReadyListener = goog.bind(this.onPlayerReady, this);

  this.init();
};

yt.video.prototype.init = function() {
  var tag = document.createElement('script');
  tag.src = "http://www.youtube.com/player_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
};

/*
 * Callback function fired when YT API is ready
 * This is exported using goog.exportSymbol in another file and
 * is being fired by the API properly.
 */
yt.video.prototype.onPlayerReady = function(event) {
  // Logs [object Object]
  window.console.log('this :' + this);

  // Logs [object Object],[object Object]
  window.console.log('this.videos : ' + this.videos); 

  event.target.playVideo();
};


YT.Player次に、バインドされたイベントリスナーを次のようにオブジェクト に追加できます。

var myVideoObject = new yt.video(videos, locales);

function onYouTubePlayerAPIReady() {
  var player;
  player = new YT.Player('player', {
    width: 1280,
    height: 720,
    videoId: 'u1zgFlCw8Aw',
    events: {
      'onReady': myVideoObject.onPlayerReadyListener
    }
  });
} 
于 2012-06-11T04:14:54.597 に答える