我正在使用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
对象的上下文中定义这两个变量,有没有办法做到这一点?
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);
答案 0 :(得分:2)
如何将onYouTubePlayerAPIReady
定义为全局函数,如API期望的那样,然后从该函数内部调用onPlayerReady
方法?代码示例:
window.onYouTubePlayerAPIReady = function () {
var args = Array.prototype.slice.call(arguments);
args.push(videos, locales);
videoTemplate.onPlayerReady.apply(videoTemplate, args);
};
并修改onPlayerReady方法的签名以接受相同顺序的参数
答案 1 :(得分:1)
回答您的具体问题:
我的挑战是我想将2个变量传递给回调函数。如果没有在窗口对象的上下文中定义这两个变量,有没有办法做到这一点?
是的,有一些方法可以在不使用全局变量的情况下向回调函数提供数据。但是,在查看回调函数之前,YouTube API具有以下要求:
YouTube API examples在 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
}
});
}
您的示例回调函数yt.video.prototype.onPlayerReady
似乎是YouTube onReady
对象发出的YouTube API事件YT.Player
的事件监听器。 API文档表明在构造YT.Player
对象时添加了事件侦听器,或者使用addEventListener
函数添加了事件侦听器(Closure Library替代为goog.events.listen
)。
由于yt.video.prototype.onPlayerReady
事件监听器需要“监听”从YouTube onReady
对象发出的YT.Player
事件,因此在其中构建新的YT.Player
个实例将是循环的事件侦听器yt.video.prototype.onPlayerReady
旨在侦听YT.Player
实例发出的事件。
回到在不使用全局变量的情况下向回调函数提供数据的原始问题,您不能将任意函数参数传递给事件侦听器(例如,在上面的原始代码示例中,yt.video.prototype.onPlayerReady
必须接受{ {1}}对象作为其第一个参数而不是Event
数组)。但是,事件侦听器videos
可以用作回调函数,并且仍然可以访问yt.video.prototype.onPlayerReady
实例对象的状态,只要它绑定到{{1}的实例即可}。
将yt.video
参数绑定到特定对象的一种方法是使用Closure Library函数goog.bind(functionToCall, selfObject, var_args)。可以按如下方式修改yt.video
构造函数:
this
然后可以将绑定事件侦听器添加到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();
};