在 reactjs 中使用 HTMLAudioElement 创建简单的播放器
create simple player with HTMLAudioElement in reactjs
我正在创建一个简单播放器的网络应用程序。
我想获取正在播放的音乐的当前时间。
这是登录 useEffect
很棒。
React.useEffect(() => {
Audio.addEventListener("timeupdate", (e) => {
//setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
});
return () => {
Audio.removeEventListener("timeupdate", () => {});
};
}, []);
问题
在 state
中设置 e.target.currentTime
时。音乐播放停止。
React.useEffect(() => {
Audio.addEventListener("timeupdate", (e) => {
setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
});
return () => {
Audio.removeEventListener("timeupdate", () => {});
};
}, []);
它将与本地 Audio
元素一起工作:
import React from "react";
import Musics from "../data/Musics";
import Next from "../assets/next.svg";
import Prev from "../assets/prev.svg";
import Play from "../assets/play.svg";
import Pause from "../assets/pause.svg";
import Progress from "../components/Progress";
import MusicTitle from "../components/MusicTitle";
import Button from "../components/Button";
import Container from "../components/Container";
//import Audio from "../models/Audio";
const MusicPlayer = () => {
const [state, setState] = React.useState({
isPlaying: false,
title: Musics[0].name,
path: Musics[0].path
/**
* Define your state here
*/
});
const [currentTime, setCurrentTime] = React.useState(0);
const audio = new Audio();
audio.src = state.path;
audio.addEventListener("timeupdate", function () {
let time = this.currentTime;
setCurrentTime(time);
console.log(time);
});
const next = () => {
// TODO Implement this function
};
const prev = () => {
// TODO Implement this function
};
const play = () => {
console.log(5);
audio.play();
};
return (
<Container>
<MusicTitle title={state.title} />
<Progress currentTime={currentTime} />
<div className="row justify-content-center">
<Button data-testid="prev-btn" onClick={prev} src={Prev} />
<Button
data-testid={state.isPlaying ? "pause" : "play-btn"}
onClick={play}
src={state.isPlaying ? Pause : Play}
/>
<Button data-testid="next-btn" onClick={next} src={Next} />
</div>
</Container>
);
};
export default MusicPlayer;
编辑:回答 OP 为什么它在初始变体中不起作用
应用程序包含外部元素,不受 React 控制,因此应手动保持同步。这里,当调用 setCurrentTime
时,组件被重新评估,因此应防止重新分配 Audio.src
以不重置音频。此外,事件侦听器应该正确移除以防止内存泄漏。 (事实上 ,虽然带有本地 Audio
元素的代码正在运行,但它并不完美,并且在播放期间按下 play
将创建新的 Audio
元素并将同时播放)。以下是具有全局 Audio
元素的工作变体的更改。
import React from "react";
import Musics from "../data/Musics";
import Next from "../assets/next.svg";
import Prev from "../assets/prev.svg";
import Play from "../assets/play.svg";
import Pause from "../assets/pause.svg";
import Progress from "../components/Progress";
import MusicTitle from "../components/MusicTitle";
import Button from "../components/Button";
import Container from "../components/Container";
import Audio from "../models/Audio";
const MusicPlayer = () => {
const [state, setState] = React.useState({
isPlaying: false,
title: Musics[0].name,
path: Musics[0].path
/**
* Define your state here
*/
});
const [currentTime, setCurrentTime] = React.useState(0);
React.useEffect(() => {
const timeupdate = (e) => {
setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
};
Audio.addEventListener("timeupdate", timeupdate);
return () => {
Audio.removeEventListener("timeupdate", timeupdate);
};
});
if (!Audio.src)
Audio.src = state.path;
const next = () => {
// TODO Implement this function
};
const prev = () => {
// TODO Implement this function
};
const play = () => {
console.log(5);
Audio.play();
};
return (
<Container>
<MusicTitle title={state.title} />
<Progress currentTime={currentTime} />
<div className="row justify-content-center">
<Button data-testid="prev-btn" onClick={prev} src={Prev} />
<Button
data-testid={state.isPlaying ? "pause" : "play-btn"}
onClick={play}
src={state.isPlaying ? Pause : Play}
/>
<Button data-testid="next-btn" onClick={next} src={Next} />
</div>
</Container>
);
};
export default MusicPlayer;
我正在创建一个简单播放器的网络应用程序。
我想获取正在播放的音乐的当前时间。
这是登录 useEffect
很棒。
React.useEffect(() => {
Audio.addEventListener("timeupdate", (e) => {
//setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
});
return () => {
Audio.removeEventListener("timeupdate", () => {});
};
}, []);
问题
在 state
中设置 e.target.currentTime
时。音乐播放停止。
React.useEffect(() => {
Audio.addEventListener("timeupdate", (e) => {
setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
});
return () => {
Audio.removeEventListener("timeupdate", () => {});
};
}, []);
它将与本地 Audio
元素一起工作:
import React from "react";
import Musics from "../data/Musics";
import Next from "../assets/next.svg";
import Prev from "../assets/prev.svg";
import Play from "../assets/play.svg";
import Pause from "../assets/pause.svg";
import Progress from "../components/Progress";
import MusicTitle from "../components/MusicTitle";
import Button from "../components/Button";
import Container from "../components/Container";
//import Audio from "../models/Audio";
const MusicPlayer = () => {
const [state, setState] = React.useState({
isPlaying: false,
title: Musics[0].name,
path: Musics[0].path
/**
* Define your state here
*/
});
const [currentTime, setCurrentTime] = React.useState(0);
const audio = new Audio();
audio.src = state.path;
audio.addEventListener("timeupdate", function () {
let time = this.currentTime;
setCurrentTime(time);
console.log(time);
});
const next = () => {
// TODO Implement this function
};
const prev = () => {
// TODO Implement this function
};
const play = () => {
console.log(5);
audio.play();
};
return (
<Container>
<MusicTitle title={state.title} />
<Progress currentTime={currentTime} />
<div className="row justify-content-center">
<Button data-testid="prev-btn" onClick={prev} src={Prev} />
<Button
data-testid={state.isPlaying ? "pause" : "play-btn"}
onClick={play}
src={state.isPlaying ? Pause : Play}
/>
<Button data-testid="next-btn" onClick={next} src={Next} />
</div>
</Container>
);
};
export default MusicPlayer;
编辑:回答 OP 为什么它在初始变体中不起作用
应用程序包含外部元素,不受 React 控制,因此应手动保持同步。这里,当调用 setCurrentTime
时,组件被重新评估,因此应防止重新分配 Audio.src
以不重置音频。此外,事件侦听器应该正确移除以防止内存泄漏。 (事实上 ,虽然带有本地 Audio
元素的代码正在运行,但它并不完美,并且在播放期间按下 play
将创建新的 Audio
元素并将同时播放)。以下是具有全局 Audio
元素的工作变体的更改。
import React from "react";
import Musics from "../data/Musics";
import Next from "../assets/next.svg";
import Prev from "../assets/prev.svg";
import Play from "../assets/play.svg";
import Pause from "../assets/pause.svg";
import Progress from "../components/Progress";
import MusicTitle from "../components/MusicTitle";
import Button from "../components/Button";
import Container from "../components/Container";
import Audio from "../models/Audio";
const MusicPlayer = () => {
const [state, setState] = React.useState({
isPlaying: false,
title: Musics[0].name,
path: Musics[0].path
/**
* Define your state here
*/
});
const [currentTime, setCurrentTime] = React.useState(0);
React.useEffect(() => {
const timeupdate = (e) => {
setCurrentTime(e.target.currentTime);
console.log(e.target.currentTime);
};
Audio.addEventListener("timeupdate", timeupdate);
return () => {
Audio.removeEventListener("timeupdate", timeupdate);
};
});
if (!Audio.src)
Audio.src = state.path;
const next = () => {
// TODO Implement this function
};
const prev = () => {
// TODO Implement this function
};
const play = () => {
console.log(5);
Audio.play();
};
return (
<Container>
<MusicTitle title={state.title} />
<Progress currentTime={currentTime} />
<div className="row justify-content-center">
<Button data-testid="prev-btn" onClick={prev} src={Prev} />
<Button
data-testid={state.isPlaying ? "pause" : "play-btn"}
onClick={play}
src={state.isPlaying ? Pause : Play}
/>
<Button data-testid="next-btn" onClick={next} src={Next} />
</div>
</Container>
);
};
export default MusicPlayer;