首先,如果您能够在 iframe 本身上获取 ID,事情将大大简化,如下所示:
<span class="soundcloud_embed">
<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F4997623" id="sound1"></iframe>
</span>
<span class="soundcloud_embed">
<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F105153133" id="sound2"></iframe>
</span>
<span class="youtube_embed">
<iframe width="400" height="225" src="//www.youtube.com/embed/tv8WgLEIPBg" id="vid1" frameborder="0" allowfullscreen></iframe>
</span>
<span class="youtube_embed">
<iframe width="400" height="225" src="//www.youtube.com/embed/FmICU1gMAAw" id="vid2" frameborder="0" allowfullscreen></iframe>
</span>
如果您不想破解您提到的 auto_html gem 来获取 ID,您可以使用 jquery 的.uniqueId()
函数在所有 iframe 上生成它们,或者使用getFrameID()
您提到的帖子中的辅助方法(并且似乎已经在使用)。
为了使这两个 API(Youtube 和 Soundcloud)能够尽可能容易地响应彼此的事件,您可以使用几个控制对象来跟踪您页面上的玩家以及他们中的哪些玩家当前正在播放(此策略类似于您提到的链接所采用的策略,但已扩展为能够跟踪哪个播放器属于哪个 API)。使用它,定义一个通用的暂停函数,作为两个 API 的简单包装器:
var playerCurrentlyPlaying = {"api":null,"frameID":null};
var players = {"yt":{},"sc":{}};
pauseCurrentPlayer=function() {
var api=playerCurrentlyPlaying["api"],
frameid=playerCurrentlyPlaying["frameID"];
switch(api) {
case "yt":
players[api][frameid].pauseVideo();
break;
case "sc":
players[api][frameid]["widget"].pause();
break;
}
};
接下来,您需要定义两个单独的函数;第一个将在捕获 YouTube 播放事件时调用,第二个将在捕获 Soundcloud 播放事件时调用。目前,Soundcloud HTML5 Widget 有一些错误,迫使必须包含一些非常丑陋的 hack——即,当您第一次播放 Soundcloud 声音时,有时不会触发 Play 事件。幸运的是,Play_Progress 事件是,所以我们可以利用它,但还必须包括一个解决方法,这样它就不会在暂停声音和开始视频时产生竞争条件:
onYTPlay =function(frameid) {
if (playerCurrentlyPlaying["frameID"]!=frameid && playerCurrentlyPlaying["frameID"]!=null) {
pauseCurrentPlayer();
}
playerCurrentlyPlaying["api"]="yt";
playerCurrentlyPlaying["frameID"]=frameid;
};
onSCPlay=function(frameid,event) {
if (event==SC.Widget.Events.PLAY||players["sc"][frameid]["firstplay"]==true) {
if (playerCurrentlyPlaying["api"]=="yt") { // because any soundcloud player will be automatically paused by another soundcloud event, we only have to worry if the currently active player is Youtube
pauseCurrentPlayer();
}
playerCurrentlyPlaying["api"]="sc";
playerCurrentlyPlaying["frameID"]=frameid;
players["sc"][frameid]["firstplay"]=false;
}
};
最后,您可以将您的钩子添加到 Youtube 嵌入和 Soundcloud 嵌入中,记住我们必须为 Soundcloud Play 事件添加的技巧。不要忘记嵌入 Soundcloud Widget API ( <script src="w.soundcloud.com/player/api.js"; type="text/javascript"></script>
),然后使用此代码进行绑定:
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
$(".youtube_embed iframe").each(function() {
players["yt"][$(this).attr('id')] = new YT.Player($(this).attr('id'), {
events: { 'onStateChange': onYTPlayerStateChange }
});
});
}
onYTPlayerStateChange = function(event) {
if (event.data==YT.PlayerState.PLAYING) {
onYTPlay(event.target.a.id);
}
};
(function(){
$(".soundcloud_embed iframe").each(function() {
var frameid=$(this).attr('id');
players["sc"][frameid]={};
players["sc"][frameid]={"widget":SC.Widget(document.getElementById(frameid)),"firstplay":true};
players["sc"][frameid]["widget"].bind(SC.Widget.Events.READY, function() {
players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY, function() {
onSCPlay(frameid,SC.Widget.Events.PLAY);
});
players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY_PROGRESS, function() {
onSCPlay(frameid,SC.Widget.Events.PLAY_PROGRESS);
});
});
});
}());
这种方法设置为处理这两种 API 的多个播放器,并且如果您想支持其他可嵌入的媒体小部件(假设它们在开始播放时公开事件并且它们能够以编程方式暂停播放器),则应该可以很好地扩展。