我构建了一个带有倒计时器的基本网页,在倒计时的不同点播放 3 种短声,一旦倒计时完成,就会出现一个秒表计时器并等待用户按下停止键。
.play()
功能似乎在我的 iPhone 上的 Chrome 和 Safari 上都不起作用。这三种声音根本听不见。
它在桌面上运行良好,完全没有问题。
这个问题有解决办法吗? 该训练工具的整体理念是它应该在手机上运行,以便参赛者可以在家训练他们的反应时间。
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
<style>
#processed-content {
background-image: url('https://www.slslnc.org.au/wp-content/uploads/timerbackground.jpg');
background-position: center;
background-size: cover;
min-height: 96vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px;
text-align: center;
}
#processed-content h1,
#processed-content p {
color: black;
text-shadow: 0 0 15px white;
font-size: 2rem;
margin:50px 0;
}
p#timerDisplay.instructions {
font-size: 18px !important;
}
#processed-content button {
color: black;
font-size: 2rem;
margin:20px 0;
}
.start-button {
background-color:#ffd520;
border:2px solid black;
}
.stop-button {
background-color:#ed1c2e;
border:2px solid black;
}
.reset-button {
background-color:#00cc36;
border:2px solid black;
}
.save-button {
background-color:#0066db;
border:2px solid black;
}
.hidden {
display: none;
}
@media screen and (max-width:768px) {
p#timerDisplay.instructions {
font-size: 18px !important;
}
}
</style>
<div id="processed-content">
<h1 class="text-2xl font-bold mb-4">Beach Flags Reaction Time Trainer</h1>
<button id="startButton" class="bg-gold hover:bg-gray-200 text-black font-bold py-4 px-10 rounded mb-4 start-button">START</button>
<p id="timerDisplay" class="text-lg mb-4 instructions">When you press START, you will have up to 15 seconds to get into position and be ready for the audio prompts...</p>
<button id="stopButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-4 px-10 rounded mb-4 stop-button">STOP</button>
<button id="resetButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-2 px-4 rounded reset-button">RESET</button>
<button id="screenshotButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-2 px-4 rounded mt-4 save-button">SAVE SCREENSHOT</button>
</div>
<audio id="readyAudio" src="https://www.slslnc.org.au/wp-content/uploads/competitorsready.mp3"></audio>
<audio id="headsDownAudio" src="https://www.slslnc.org.au/wp-content/uploads/headsdown.mp3"></audio>
<audio id="whistleAudio" src="https://www.slslnc.org.au/wp-content/uploads/whistle.mp3"></audio>
<script>
const startButton = document.getElementById("startButton");
const stopButton = document.getElementById("stopButton");
const resetButton = document.getElementById("resetButton");
const screenshotButton = document.getElementById("screenshotButton");
const timerDisplay = document.getElementById("timerDisplay");
const readyAudio = document.getElementById("readyAudio");
const headsDownAudio = document.getElementById("headsDownAudio");
const whistleAudio = document.getElementById("whistleAudio");
let countdownTimeout, headsDownTimeout, whistleTimeout, stopwatchInterval;
let startTime;
startButton.addEventListener("click", function() {
startButton.classList.add("hidden");
timerDisplay.textContent = "Get ready...";
const randomCountdown = Math.floor(Math.random() * 6) + 10;
countdownTimeout = setTimeout(() => {
readyAudio.play();
const randomReadyTime = Math.floor(Math.random() * 2) + 3;
headsDownTimeout = setTimeout(() => {
headsDownAudio.play();
const randomWhistleTime = Math.floor(Math.random() * 3) + 2;
whistleTimeout = setTimeout(() => {
whistleAudio.play();
startStopwatch();
}, randomWhistleTime * 1000);
}, randomReadyTime * 1000);
}, randomCountdown * 1000);
});
function startStopwatch() {
startTime = Date.now();
stopButton.classList.remove("hidden");
stopwatchInterval = setInterval(() => {
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
timerDisplay.textContent = `Time: ${elapsedTime} s`;
}, 10);
}
stopButton.addEventListener("click", function() {
clearInterval(stopwatchInterval);
stopButton.classList.add("hidden");
resetButton.classList.remove("hidden");
screenshotButton.classList.remove("hidden");
});
resetButton.addEventListener("click", function() {
clearTimeout(countdownTimeout);
clearTimeout(headsDownTimeout);
clearTimeout(whistleTimeout);
timerDisplay.textContent = "Get ready...";
resetButton.classList.add("hidden");
screenshotButton.classList.add("hidden");
startButton.classList.remove("hidden");
});
screenshotButton.addEventListener("click", function() {
html2canvas(document.querySelector("#processed-content")).then(canvas => {
const link = document.createElement('a');
link.href = canvas.toDataURL();
link.download = 'reaction_time.png';
link.click();
});
});
function loadHtml2Canvas() {
const script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";
document.body.appendChild(script);
}
loadHtml2Canvas();
</script>
这个问题已经在 Stackoverflow 上有了解决方案,所以我投票决定关闭。但正如您所说,您不是开发人员,也不知道如何简化代码,我在此处插入了一个解决方法到您的代码中,只是为了帮助您入门。
对于此片段播放的每个音频,然后在单击“开始”时立即暂停。这使得它可以在移动设备上的 setTimeouts 内播放(真正恢复播放)。
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
<style>
#processed-content {
background-image: url('https://www.slslnc.org.au/wp-content/uploads/timerbackground.jpg');
background-position: center;
background-size: cover;
min-height: 96vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px;
text-align: center;
}
#processed-content h1,
#processed-content p {
color: black;
text-shadow: 0 0 15px white;
font-size: 2rem;
margin:50px 0;
}
p#timerDisplay.instructions {
font-size: 18px !important;
}
#processed-content button {
color: black;
font-size: 2rem;
margin:20px 0;
}
.start-button {
background-color:#ffd520;
border:2px solid black;
}
.stop-button {
background-color:#ed1c2e;
border:2px solid black;
}
.reset-button {
background-color:#00cc36;
border:2px solid black;
}
.save-button {
background-color:#0066db;
border:2px solid black;
}
.hidden {
display: none;
}
@media screen and (max-width:768px) {
p#timerDisplay.instructions {
font-size: 18px !important;
}
}
</style>
<div id="processed-content">
<h1 class="text-2xl font-bold mb-4">Beach Flags Reaction Time Trainer</h1>
<button id="startButton" class="bg-gold hover:bg-gray-200 text-black font-bold py-4 px-10 rounded mb-4 start-button">START</button>
<p id="timerDisplay" class="text-lg mb-4 instructions">When you press START, you will have up to 15 seconds to get into position and be ready for the audio prompts...</p>
<button id="stopButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-4 px-10 rounded mb-4 stop-button">STOP</button>
<button id="resetButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-2 px-4 rounded reset-button">RESET</button>
<button id="screenshotButton" class="hidden bg-white hover:bg-gray-200 text-black font-bold py-2 px-4 rounded mt-4 save-button">SAVE SCREENSHOT</button>
</div>
<audio id="readyAudio" src="https://www.slslnc.org.au/wp-content/uploads/competitorsready.mp3"></audio>
<audio id="headsDownAudio" src="https://www.slslnc.org.au/wp-content/uploads/headsdown.mp3"></audio>
<audio id="whistleAudio" src="https://www.slslnc.org.au/wp-content/uploads/whistle.mp3"></audio>
<script>
const startButton = document.getElementById("startButton");
const stopButton = document.getElementById("stopButton");
const resetButton = document.getElementById("resetButton");
const screenshotButton = document.getElementById("screenshotButton");
const timerDisplay = document.getElementById("timerDisplay");
const readyAudio = document.getElementById("readyAudio");
const headsDownAudio = document.getElementById("headsDownAudio");
const whistleAudio = document.getElementById("whistleAudio");
let countdownTimeout, headsDownTimeout, whistleTimeout, stopwatchInterval;
let startTime;
startButton.addEventListener("click", function() {
//ADDED for mobile devices. Audio needs to be started directly on a click otherwise it wont play in the timeout
readyAudio.play();
readyAudio.pause();
headsDownAudio.play();
headsDownAudio.pause();
whistleAudio.play();
whistleAudio.pause();
startButton.classList.add("hidden");
timerDisplay.textContent = "Get ready...";
const randomCountdown = Math.floor(Math.random() * 6) + 10;
countdownTimeout = setTimeout(() => {
readyAudio.play();
const randomReadyTime = Math.floor(Math.random() * 2) + 3;
headsDownTimeout = setTimeout(() => {
headsDownAudio.play();
const randomWhistleTime = Math.floor(Math.random() * 3) + 2;
whistleTimeout = setTimeout(() => {
whistleAudio.play();
startStopwatch();
}, randomWhistleTime * 1000);
}, randomReadyTime * 1000);
}, randomCountdown * 1000);
});
function startStopwatch() {
startTime = Date.now();
stopButton.classList.remove("hidden");
stopwatchInterval = setInterval(() => {
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2);
timerDisplay.textContent = `Time: ${elapsedTime} s`;
}, 10);
}
stopButton.addEventListener("click", function() {
clearInterval(stopwatchInterval);
stopButton.classList.add("hidden");
resetButton.classList.remove("hidden");
screenshotButton.classList.remove("hidden");
});
resetButton.addEventListener("click", function() {
clearTimeout(countdownTimeout);
clearTimeout(headsDownTimeout);
clearTimeout(whistleTimeout);
timerDisplay.textContent = "Get ready...";
resetButton.classList.add("hidden");
screenshotButton.classList.add("hidden");
startButton.classList.remove("hidden");
});
screenshotButton.addEventListener("click", function() {
html2canvas(document.querySelector("#processed-content")).then(canvas => {
const link = document.createElement('a');
link.href = canvas.toDataURL();
link.download = 'reaction_time.png';
link.click();
});
});
function loadHtml2Canvas() {
const script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";
document.body.appendChild(script);
}
loadHtml2Canvas();
</script>