0
我想添加一個使用SoundManager2的音頻Javascript插件的事件處理程序。這是播放一首歌曲,等待歌曲結束時再次執行該函數的功能:爲什麼事件觸發不止一次?
function songPlay (newSrc) {
htmlSound.src = newSrc;
htmlSound.load();
thisPlayer.find(".total-position-scrubber").bind("slide", function(event, ui) {
htmlSound.currentTime = ui.value;
});
var currentArtist = currentRow.find(".total-artist").text();
var currentTitle = currentRow.find(".total-title").text();
thisPlayer.find(".total-playing-artist").html(currentArtist);
thisPlayer.find(".total-playing-title").html(currentTitle);
htmlSound.addEventListener("timeupdate", function() {
var newVolume = thisPlayer.find(".total-volume-slider").slider("option", "value");
htmlSound.volume = newVolume;
var duration = htmlSound.duration * 1000;
var durationTime = convertMilliseconds(duration, "mm:ss");
thisPlayer.find(".total-song-duration").html(durationTime.clock);
var position = htmlSound.currentTime * 1000;
var positionTime = convertMilliseconds(position, "mm:ss");
thisPlayer.find(".total-song-position").html(positionTime.clock);
thisPlayer.find(".total-position-scrubber").slider("option", "max", duration/1000);
thisPlayer.find(".total-position-scrubber").slider("option", "value", position/1000);
});
htmlSound.addEventListener("ended", function() {
// Find next checked song
currentRow = currentRow.nextAll(".can-play:first");
// If checked song exists after current song, load it
if(currentRow.length > 0)
{
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
else
{
// If no checked song exists after current song, load the first checked song in playlist
if(thisPlayer.find(".can-play").length > 0)
{
currentRow = thisPlayer.find(".can-play:first");
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
// Change pause button to play button
else
{
thisPlayer.find(".total-play").removeClass("total-pause");
}
}
// If song is playing while next button is clicked play next song
if(thisPlayer.find(".total-pause").length > 0)
{
htmlSound.play();
}
});
thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
currentRow.find(".total-not-playing").addClass("total-playing");
}
唯一的問題是,「結束」事件被觸發不是每次一遍,一首歌結束。在「結束」事件之後,該功能被執行,然後再次執行songPlay()
函數(這是預期的行爲),但是然後,在歌曲結束之前再次觸發「結束」事件,同時它應該等待爲歌曲的結尾。任何關於這種行爲的原因的想法?
newSrc
變量總是正確的值。
這是SoundManager2的 「結束」 事件定義:
_html5_events = {
// HTML5 event-name-to-handler map
...
ended: _html5_event(function() {
var t = this._t;
_s._wD(_h5+'ended: '+t.sID);
t._onfinish();
}),
...
}
編輯:
出人意料的是,它的工作只是一個聲明的函數替代匿名函數是這樣的:
function eventListenerFunction() {
// Find next checked song
currentRow = currentRow.nextAll(".can-play:first");
// If checked song exists after current song, load it
if(currentRow.length > 0)
{
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
else
{
// If no checked song exists after current song, load the first checked song in playlist
if(thisPlayer.find(".can-play").length > 0)
{
currentRow = thisPlayer.find(".can-play:first");
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
// Change pause button to play button
else
{
thisPlayer.find(".total-play").removeClass("total-pause");
}
}
// If song is playing while next button is clicked play next song
if(thisPlayer.find(".total-pause").length > 0)
{
htmlSound.play();
}
});
function songPlay (newSrc) {
htmlSound.src = newSrc;
htmlSound.load();
thisPlayer.find(".total-position-scrubber").bind("slide", function(event, ui) {
htmlSound.currentTime = ui.value;
});
var currentArtist = currentRow.find(".total-artist").text();
var currentTitle = currentRow.find(".total-title").text();
thisPlayer.find(".total-playing-artist").html(currentArtist);
thisPlayer.find(".total-playing-title").html(currentTitle);
htmlSound.addEventListener("timeupdate", function() {
var newVolume = thisPlayer.find(".total-volume-slider").slider("option", "value");
htmlSound.volume = newVolume;
var duration = htmlSound.duration * 1000;
var durationTime = convertMilliseconds(duration, "mm:ss");
thisPlayer.find(".total-song-duration").html(durationTime.clock);
var position = htmlSound.currentTime * 1000;
var positionTime = convertMilliseconds(position, "mm:ss");
thisPlayer.find(".total-song-position").html(positionTime.clock);
thisPlayer.find(".total-position-scrubber").slider("option", "max", duration/1000);
thisPlayer.find(".total-position-scrubber").slider("option", "value", position/1000);
});
htmlSound.addEventListener("ended", eventListenerFunction)
thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
currentRow.find(".total-not-playing").addClass("total-playing");
}
但是,我想我應該使用$('body').off("ended")
後像@Fallenreaper建議的那樣觸發函數來移除事件監聽器。
仔細檢查所有基本情況。由於有些情況下,您可以在歌曲播放器內部應用的監聽器中調用歌曲播放功能,因爲您點擊時會有一個循環結構,它將繼續應用新的監聽器。 – Fallenreaper
@Fallenreaper - 但我想每次都應用一個新的監聽器,那麼爲什麼不在監聽器函數中再次調用該函數呢? – Manolo
您可能想要刪除先前的偵聽器和REAPPLY,而不是追加新的偵聽器。問題在於你點擊並且事件觸發一次,然後再次點擊它會觸發兩次,再次點擊,觸發4次等。如果你想申請一個新的偵聽器,你可以,但是我會相應地通知你。你會想要覆蓋原來的。這樣做和$(「item」)一樣簡單。off(「functionName」);在jQuery中。 – Fallenreaper