一页上多个音频文件的 Javascript 音频控件问题

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

网络开发人员变身配音演员!我正在为后者开发我的个人网站,并且在为音频文件设置自定义控件时遇到了很多问题。我正在使用以下代码加载我的音频文件......

<section id="demos widthWrap">
        <?php
            $aniURL = get_field('animation');
            $comURL = get_field('commercial');

            $demos = array(
                "aniDemo" => array(
                    "Kind" => "Animation",
                    "URL" => $aniURL
                ),
                "comDemo" => array(
                    "Kind" => "Commercial",
                    "URL" => $comURL
                )
            );

            foreach ($demos as $demo){
                ?>
                <figure class="demoBox">
                    <audio class="demo" controls preload="metadata">
                        <source src="<?php echo $demo["URL"];?>" type="audio/mp3">
            <!-- Put a small fallback message for old browsers -->
                        <p>ERROR! Your browser does not support audio playback!</p>
                    </audio>
                    <ul class="demoControls">
                        <li class="playButton"><button class="playPause"><i class="fa-solid fa-play"></i></button></li>
                        <li class="progress">
                            <progress class="progressBar" value="0" min="0"></progress>
                        </li>
                    </ul>
                </figure>
                <?php
            }
        ?>
</section>

…并且这些正在正确加载。用于自定义控件的 Javascript 会出现问题。在这里。

const supportsAudio = !!document.createElement("audio").canPlayType;
if (supportsAudio) {
    const audioContaner = document.getElementsByClassName("demoBox");
    const audio = document.getElementsByClassName("demo");
    const audioControls = document.getElementsByClassName("demoControls");

    // Hide the default controls
    audio.controls = false;

    // Display the user defined audio controls
    audioControls.style.display = "block";

    const playPause = document.getElementsByClassName("playPause");
    const progress = document.getElementsByClassName("progressBar");

    playPause.addEventListener("click", (e) => {
        if (audio.paused || audio.ended){
            audio.play();
            //switch to pause icon
        } else {
            audio.pause();
            //switch to play icon
        }
    });
    playPause.addEventListener(ended, (e)=> {
        console.log("Audio has ended");
        //switch to repeat icon
    });

    audio.addEventListener("loadedmetadata", () => {
        progress.setAttribute("max", audio.duration)
    });
    audio.addEventListener("timeupdate", () => {
        if (!progress.getAttribute("max"))
            progress.setAttribute("max", audio.duration);
        progress.value = audio.currentTime;
    });
}

我的大部分内容都基于这篇 MDN 文章,只挑选我需要的部分并调整音频内容。我还尝试更改一些内容以适用于音频文件的多个实例,我很确定这就是事情出现问题的地方。

将audioControls样式设置为display:block时,我收到“未捕获的类型错误:无法设置未定义的属性(设置'显示')”,但问题早在这之前就开始了。音频.controls = false;没有摆脱默认的播放控件,表明问题可能出在我的声明上。我使用 getElementsByClassName 声明的所有内容都作为 HTMLCollection (我刚刚了解到这是一个东西) 出现,并且尝试迭代其中任何一个都不会给出任何结果。我尝试了一些不同的 for…of 循环,并尝试将最高相关 DOM 元素的声明转换为数组,并尝试了 forEach ,并从我的 console.log 尝试中得到了记录。

作为专业要求,我需要将所有演示放在一页上(代理不想去多个页面听演示),并且真的不想为每个实例编写所有 Javascript音频文件。我该怎么办?

html5-audio web-audio-api
1个回答
0
投票

...并且尝试迭代其中任何一个都不会给出任何结果。

这就是问题所在。您正在尝试设置

HTMLCollection
的属性,它基本上是
getElementsByClassName
找到的元素列表。

这里的解决方案是选择所有

demoBox
元素并循环遍历它们。然后,对于每个
demoBox
,选择其中的所有元素并设置事件侦听器和设置。

就我个人而言,我更喜欢使用

querySelector()
querySelectorAll()
而不是
getElementsByClassName()
,因为它们可以更好地控制您正在寻找的内容并给出可预测的结果。它们可以在元素级别上使用,这正是我们这里所需要的。

const audioContainers = document.querySelectorAll(".demoBox");

// Loop over each .demoBox element.
for (const audioContainer of audioContainers) {
  const audio = audioContainer.querySelector(".demo");
  const audioControls = audioContainer.querySelector(".demoControls");

  // Hide the default controls
  audio.controls = false;

  // Display the user defined audio controls
  audioControls.style.display = "block";

  const playPause = audioControls.querySelector(".playPause");
  const progress = audioControls.querySelector(".progressBar");

  playPause.addEventListener("click", (e) => {
    if (audio.paused || audio.ended) {
      audio.play();
      //switch to pause icon
    } else {
      audio.pause();
      //switch to play icon
    }
  });

  playPause.addEventListener(ended, (e) => {
    console.log("Audio has ended");
    //switch to repeat icon
  });

  audio.addEventListener("loadedmetadata", () => {
    progress.setAttribute("max", audio.duration);
  });

  audio.addEventListener("timeupdate", () => {
    if (!progress.getAttribute("max")) {
      progress.setAttribute("max", audio.duration);
    }

    progress.value = audio.currentTime;
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.