javascript - 一次只播放一首歌曲 (React)
问题描述
我正在尝试通过 API 创建一个音乐应用程序,在其中我为每首歌曲渲染一个歌曲组件,每首歌曲都有自己的播放、暂停和停止按钮,但是当我在播放歌曲时播放另一首歌曲时,我想要前一首将停止播放。就像其他音乐应用程序一样。
这是处理播放、暂停和停止的组件
const useAudio = (song_url) => {
const audio = useRef(new Audio(song_url));
audio.current.preload = "metadata";
const [isPlaying, setPlaying] = useState(false);
const toggleAudio = () => {
setPlaying(!isPlaying);
};
const handleStop = () => {
audio.current.pause();
audio.current.currentTime = 0;
setPlaying(false);
};
useEffect(() => {
isPlaying ? audio.current.play() : audio.current.pause();
}, [isPlaying]);
useEffect(() => {
audio.current.addEventListener("ended", () => setPlaying(false));
return () => {
audio.current.removeEventListener("ended", () => setPlaying(false));
};
}, []);
return [isPlaying, toggleAudio, handleStop];
};
解决方案
每次调用 useAudio 时,您都在创建具有独立状态的钩子的新实例,因此您无法控制从一个钩子到另一个钩子。
为了用一个钩子控制所有歌曲,您可能应该创建一个商店。
这是我将要做的一个简短示例。请根据您的需要进行必要的更改。
//We first create a store
export const AudioContext = createContext();
export const useAudio = () => {
const context = useContext(AudioContext);
if (!context && typeof window !== 'undefined') {
throw new Error(`useAudio must be used within a AudioContext `);
}
return context;
};
//Then we create the provider
export const AudioProvider = ({ children }) => {
const [ song, _setSong ] = useState()
const setSong = (url) => {
song.pause();
const newSong = new Audio(url)
newSong.play()
setSong(newSong)
}
const pauseSong = () => song.pause()
return <AudioContext.Provider value={{ setSong, pauseSong }}>{children}</AudioContext.Provider>
}
然后你应该用<AudioProvider>
用法:
const { setSong, pauseSong } = useAudio()
const songSelected = (url) => setSong(url)
setSong
会先暂停原曲,然后用新的url创建一个新的Audio对象,然后播放。
一次只能播放一首歌曲。
推荐阅读
- docker - 如何使用提交的哈希构建 Docker 镜像
- ruby - 如何每 x 秒启动一个新线程
- javascript - 将 JS 代码应用于动态创建的 Range Slider
- javascript - SlateJs RenderMark 在多个插件中
- java - 如何使用处理和 UDP 接收 Tello 无人机的视频流
- node.js - 溢出排序阶段缓冲的 33554438 字节数据使用量超过了 33554432 字节的内部限制 错误?
- php - 用 php 让 html 爆炸?
- c# - SignalR 客户端接收来自仪表板客户端而不是电子商务客户端的调用
- zooming - 如何放大以适合 Autodesk forge 查看器中的确切边界框
- javascript - 向 Flask render_template 端点发出客户端 POST 请求