我试图播放音频数组列表序列,但有一些条件。用户将首先选择每个问题之间的随机问题和持续时间的下拉列表。然后单击“播放”按钮以运行。
当playIndex增加到3时,其持续时间开始依赖于用户的下拉列表。但它现在给我不明确。但是当playIndex = 4时它才起作用。为什么会这样?
当playIndex增加到8(播放第7个元素后)并且随机问题的数量大于4时,它将调用随机函数为playIndex和play生成随机值(数字4到7)。但我的代码只做了一次。这是为什么?
我需要尽可能多的时间来做用户想要的事情(下拉' numFollowUp')和减4,因为在第一轮中,代码从元素0到7播放,我不会这样做需要计算前4次(元素4到7)。
播放所有随机问题后,playIndex应为
如果我迷惑你,请告诉我。非常感谢你的帮助。
<select id="numFollowUp" name="numFollowUp" style=display:none>
<option value="">Number of follow-up questions</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
</select>
<select id="secFollowUp" name="secFollowUp" style=display:none>
<option value="">Second between each question</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
</select>
$("#ImageEnterVariables").on("click", function() {
$('#ImageEnterVariables').hide();
$("#numFollowUp").show();
$("#secFollowUp").show();
$("#subBut").show();
$("#pause").hide();
});
var intro_playList = [{
"duration": 11, // in seconds, real file duration
"key": "1_hello",
"delayAfter": 6, // in seconds, delay after file ended
"stage": "intro",
"runThrough": true,
"random": false
}, {
"duration": 4,
"key": "2_how_old",
"delayAfter": 6,
"stage": "intro",
"runThrough": true,
"random": false
}, {
"duration": 3,
"key": "3_what_did_you_make",
"delayAfter": 10,
"stage": "intro",
"runThrough": true,
"random": false
}, {
// story_playlist
"duration": 5,
"key": "4_tell_me_a_story",
"stage": "story",
"runThrough": true,
"random": false
}, {
"duration": 4,
"key": "5_and_then_what",
"stage": "story",
"runThrough": true,
"random": true
}, {
"duration": 2,
"key": "6_why",
"stage": "story",
"runThrough": true,
"random": true
}, {
"duration": 3,
"key": "7_tell_me_more",
"stage": "story",
"runThrough": true,
"random": true
}, {
"duration": 3,
"key": "8_what_happened_next",
"stage": "story",
"runThrough": true,
"random": true
}, {
"duration": 4,
"key": "9_how_does_it_end",
"stage": "ending",
"runThrough": false,
"random": false
}, {
"duration": 4,
"key": "10_what_is_the_story_name",
"stage": "ending",
"runThrough": false,
"random": false
}, {
"duration": 6,
"key": "11_thank_you_goodbye",
"stage": "ending",
"runThrough": false,
"random": false
}];
$(document).ready(function() {
// Version 1
var audioElement = document.createElement('audio');
audioElement.addEventListener("ended", playAudio);
var audioSrc = "sound/"
var audioType = ".wav";
var defaultNumFollowUp = 1; // default number of random question, if user this used the dropdown
var defaultSecFollowUp = 10; // default delay (seconds) between random questions, if user this used the dropdown
// Analyse the scenario by getting indexes in different arrays.
var endingArr = [];
var runThroughArr = [];
var randomArr = [];
for(i = 0; i < intro_playList.length ; i++){
if(intro_playList[i].stage === "ending"){ endingArr.push(i); }
if(intro_playList[i].runThrough){ runThroughArr.push(i); }
if(intro_playList[i].random){ randomArr.push(i); }
}
function getAudio(n){
audioElement.src = audioSrc + intro_playList[n].key + audioType;
audioElement.load();
audioElement.play();
return intro_playList[n]; // return the object
}
// Onload indexes.
var playIndex = 0;
var randomplayCount = 0;
var endingCount = 0;
// Interval variables
var playInterval;
var time = new Date().getTime();
console.log(time + " is old time");
// User inputs
var numFollowUp = parseInt($("#numFollowUp").val());
if(isNaN(numFollowUp)){ numFollowUp = defaultNumFollowUp; }
var secFollowUp = parseInt($("#secFollowUp").val());
if(isNaN(secFollowUp)){ secFollowUp = defaultSecFollowUp; }
$("#play").on("click", playAudio);
function playAudio(){
playInterval = setInterval(function(){ // Every 0.1 second, do setInterval
var now = new Date().getTime();
//console.log(now + " now time");
if(now > time){
// First "run throught" plays all the audios in order, except the "ending" ones.
// playIndex = 0 in the first place
if(playIndex < runThroughArr.length){
var audioIndex = playIndex;
console.log("================================== RUN THROUGH!");
console.log("audioIndex is " + audioIndex);
playIndex++;
}else if (playIndex >= runThroughArr.length && randomplayCount <= numFollowUp){
var audioIndex = randomArr[ Math.floor(Math.random()*(randomArr.length - 1)) ];
console.log("================================== RUN random!");
// Increment index for next iteration
randomplayCount++;
console.log(randomplayCount);
}else if (randomplayCount >= defaultNumFollowUp && endingCount < endingArr.length ){
var audioIndex = endingArr[endingCount];
console.log("================================== RUN ending!");
// Increment index for next iteration
endingCount++;
}
// STOP INTERVAL!
if( endingCount === endingArr.length ){
clearInterval(playInterval);
console.log("=========== Interval stopped.");
// Reset onload indexes.
playIndex = 0;
randomplayCount = 0;
endingCount = 0;
}
// Prepare the audio file.
var audioObj = getAudio(audioIndex);
if(audioObj.stage === "intro"){
// set a new trigger time
time = new Date().getTime() + (audioObj.duration * 1000) + (audioObj.delayAfter * 1000);
console.log(time + " is time");
}else{
time = new Date().getTime() + (audioObj.duration * 1000) + (secFollowUp * 1000);
}
// Show what is actually playing
console.log("Playing "+ audioObj.key + " after " + audioObj.delayAfter + " seconds");
console.log("Stage: "+ audioObj.stage);
} // if(now > time)
}, 100); // playInterval, The interval duration of 0,1 second is to ensure accuracy if you set a duration or "delayAfter" using float seconds like 2.5.
} // playAudio
// Preload all audios to make sure they are available since timing is sometimes short.
var preloadArr = [];
for(i = 0; i < intro_playList.length; i++){
var audioElementPreload = document.createElement('audio');
audioElementPreload.src = audioSrc + intro_playList[i].key + audioType;
audioElementPreload.load();
preloadArr.push(audioElementPreload);
}
});
答案 0 :(得分:1)
我从头开始完全重写你的代码...... 第二次!
我认为这真的是一个很好的项目......还有一个很好的编码挑战。
在第二次教导中,我在使用setTimeout()
的第一个延迟“概念”中看到了几个问题:
setTimeout()
,这太可怕了。所以我认为使用setInterval()
来检查“实际时间”与脚本在每次迭代时设置开始下一个音频(基于文件持续时间+延迟)的时间相比...将是一个想法。
它有效!它简化了代码 所有“场景”信息现在都在对象数组中。
var audioSrc = "https://www.bessetteweb.com/SO/45704602/"; // Path to the audio files
var audioType = ".mp3";
var default_numFollowUp = 4; // default number of random question, if user this used the dropdown
var default_secFollowUp = 10; // default delai (seconds) between random questions, if user this used the dropdown
// Create the audio element
var audioElement = document.createElement('audio');
// Analyse the scenario by getting indexes in different arrays.
var endingArr = [];
var runThoughArr = [];
var randomArr = [];
for(i=0;i<intro_playList.length;i++){
if(intro_playList[i].stage == "ending"){ endingArr.push(i); }
if(intro_playList[i].runThough){ runThoughArr.push(i); }
if(intro_playList[i].random){ randomArr.push(i); }
}
// Get an audio and play it
function getAudio(n){
audioElement.src = audioSrc + intro_playList[n].key + audioType;
audioElement.load();
audioElement.play();
console.log(JSON.stringify(intro_playList[n]));
return intro_playList[n]; // return the object
}
// Onload indexes.
var playIndex = 0;
var randomplayCount = 0;
var endingCount = 0;
// Interval variables
var playInterval;
var time = new Date().getTime();
// Function to start the interval check to play a file
function playAudio(){
// User inputs
var numFollowUp = parseInt($("#numFollowUp").val() );
if(isNaN(numFollowUp)){ numFollowUp = default_numFollowUp;}
var secFollowUp = parseInt($("#secFollowUp").val() );
if(isNaN(secFollowUp)){ secFollowUp = default_secFollowUp; }
// Ensure no other interval runs...
clearInterval(playInterval);
// Set the interval.
playInterval = setInterval(function(){
var now = new Date().getTime();
if(now > time){
// First "run throught" plays all the audios in order, except the "ending" ones.
if( playIndex < runThoughArr.length){
var audioIndex = playIndex;
console.log("==================================================================== RUN TROUGH!");
// Increment index for next iteration
playIndex++;
}
// Random!
else if( playIndex >= runThoughArr.length && randomplayCount < numFollowUp ){
//var audioIndex = getRandomIndex();
var audioIndex = randomArr[ Math.floor(Math.random()*(randomArr.length-1)) ];
console.log("==================================================================== RANDOM! ("+randomplayCount+"/"+numFollowUp+")");
// Increment index for next iteration
randomplayCount++;
}
// Ending
else if( randomplayCount >= numFollowUp && endingCount < endingArr.length ){
var audioIndex = endingArr[endingCount];
console.log("==================================================================== ENDING!");
// Increment index for next iteration
endingCount++;
}
// STOP INTERVAL!
if( endingCount == endingArr.length ){
clearInterval(playInterval);
console.log("=========== Interval stopped.");
// Reset onload indexes.
playIndex = 0;
randomplayCount = 0;
endingCount = 0;
}
// Prepare the audio file.
var audioObj = getAudio(audioIndex);
if(audioObj.stage == "intro"){
// set a new trigger time
time = new Date().getTime() + (audioObj.duration * 1000) + (audioObj.delayAfter * 1000);
}else{
time = new Date().getTime() + (audioObj.duration * 1000) + (secFollowUp * 1000);
}
// Show what is actually playing
console.log("Playing "+ audioObj.key);
console.log("Stage: "+ audioObj.stage);
} // if(now > time)
},100); // interval
} // playAudio()
// Preload all audios to make sure they are available since timing is sometimes short.
var preloadArr = [];
for(i=0;i<intro_playList.length;i++){
var audioElementPreload = document.createElement('audio');
audioElementPreload.src = audioSrc + intro_playList[i].key + audioType;
audioElementPreload.load();
preloadArr.push(audioElementPreload);
}
// Play button handler
$("#play").on("click", playAudio);
答案 1 :(得分:1)
如果正确解释问题,您可以使用.queue()
,.promise()
,.then()
并重复安排对完整数组执行操作while
循环{{1}和.splice()
.splice()
和Math.random()
将原始数组的N个元素作为新数组,从切片数组中选择一个伪随机元素,重复原始任务,然后使用重复任务原始数组来完成程序。
Math.floor()
&#13;
var arr = [...Array(9).keys()],
currentRandomTracks = [],
notify = function notify(message) {
$("body").append(message + "<br>")
}
var player = $({});
function playTracks(tracks) {
return player.queue("tracks", $.map(tracks, function(el, index) {
return function(next) {
return new Promise(function(resolve) {
// do stuff
setTimeout(function() {
resolve(el);
}, Math.floor(Math.random() * 750))
}).then(function(value) {
notify(value);
// call `next` when synchronous or asynchronous task completes
return next()
})
}
})).dequeue("tracks").promise("tracks")
}
function handleRandomQueue() {
// select N elements from `arr`
if (currentRandomTracks.length === 0) {
currentRandomTracks = arr.slice(6);
var randomTracks = [];
// select random elements from `currentRandomTracks`
while (currentRandomTracks.length) {
randomTracks[randomTracks.length] = currentRandomTracks
.splice(Math.floor(Math.random() * currentRandomTracks.length), 1)
.pop();
}
notify("original playlist done playing, "
+ "starting playing random indexes "
+ currentRandomTracks.toString() + " next"
);
return playTracks(randomTracks)
} else {
notify("random playback playlist complete, "
+ "stating playing original playlist "
+ arr.toString()
);
// perform task on original array, again
return playTracks(arr);
}
}
function handleRepeatOriginalQueue() {
notify("original and random playlist playback complete");
return playTracks(arr);
}
function handleQueueComplete() {
// procedure complete
notify("original, random, "
+ "and second original playlist playback complete"
);
}
$(function() {
playTracks(arr)
.then(handleRandomQueue)
.then(handleRepeatOriginalQueue)
.then(handleQueueComplete)
.fail(function err(err) {
console.error(err)
})
})
&#13;