在 iOS 设备上的网站中播放音频时出现问题

问题描述 投票:0回答:1

我构建了一个带有倒计时器的基本网页,在倒计时的不同点播放 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>

javascript tailwind-css
1个回答
0
投票

这个问题已经在 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>

© www.soinside.com 2019 - 2024. All rights reserved.