【问题标题】:How to toggle audio in React functional component如何在 React 功能组件中切换音频
【发布时间】:2021-07-16 03:17:10
【问题描述】:

单击<img /> 时,我正在尝试播放/停止音频。每个<img /> 都与不同的音频文件相关。音频应该在用户不停止的情况下循环播放。我更喜欢不使用类组件,因为我可以使用钩子。

我的实际代码不会停止音频;不要循环它;如果我单击两次,音频就会重叠(同时发出两个声音)。

import myJSON from "./assets/myJSON.json";

export default function Card() {
 
    const handleClick = (argument) => {
        new Audio(argument.target.dataset.sound).play()
    }
    
    return (
        <>
            {myJSON.map((myObject, index) => {
                return (
                    <img
                        src={myObject.image}
                        alt={myObject.name}
                        key={index}
                        onClick={handleClick} 
                        data-sound={myObject.sound}
                    />
                );
            })}
        </>
    );
}

我可以随意更改 json 或尝试不同的方法。

【问题讨论】:

  • 您的点击事件所做的只是播放 URL... 您需要添加状态以允许组件知道它当前是否正在播放。并根据需要修改状态...
  • 同意,我建议还使用 ref 来存储当前正在播放的音频元素,以便您可以切换该流的播放/暂停状态。如果用户点击播放另一个声音,您还可以停止任何正在播放的流(除非您希望它们同时播放)。

标签: reactjs react-hooks html5-audio


【解决方案1】:

我为您创建了一个代码沙箱,您可以在此处访问:https://codesandbox.io/s/silly-hypatia-8fwun?file=/src/App.js

我已经创建了一个示例,说明我将如何按照这些思路处理某事:

请注意:数组的顺序很重要,因为我要离开索引来决定播放什么歌曲,不播放什么歌曲。您不一定必须采用这种方法。这只是一个快速而肮脏的解决方案。

import { useEffect, useState } from "react";

export default function App() {
  const [musicArray] = useState([
    "https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba-online-audio-converter.com_-1.wav",
    "https://www2.cs.uic.edu/~i101/SoundFiles/BabyElephantWalk60.wav"
  ]);
  const [data, setData] = useState([]);

  useEffect(() => {
    const musicData = musicArray.map((sound) => {
      return { audio: new Audio(sound), play: false };
    });

    setData(musicData);
  }, [musicArray]);

  const playSound = (index) => {
    setData((arr) =>
      arr.map((sound, i) => {
        if (i === index) {
          sound.audio.play();
          return { ...sound, play: true };
        }
        sound.audio.pause();
        return { ...sound, play: false };
      })
    );
  };

  useEffect(() => {
    console.log(data);
  }, [data]);

  const stopSound = (index) => {
    setData((arr) =>
      arr.map((sound, i) => {
        if (i === index) {
          sound.audio.pause();
          return { ...sound, play: false };
        }
        return { ...sound, play: false };
      })
    );
  };

  return (
    <div className="App">
      {data.map((sound, i) => {
        return (
          <>
            {sound.play ? (
              <button onClick={() => stopSound(i)}>pause</button>
            ) : (
              <button onClick={() => playSound(i)}>play</button>
            )}
          </>
        );
      })}

      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}


【讨论】:

  • 非常感谢您的帮助。但是在if ( ) { } 之后的stopSound 内部我们有return { ...sound, play: false };,我不确定,但我认为只有return { ...sound }; 也可以。
  • 但没问题!
猜你喜欢
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 2020-06-22
  • 2021-05-29
相关资源
最近更新 更多