我正在使用 Bootstrap 在 React 中开发一个自定义音频播放器,我希望能够快进或快退 5 秒播放。 我还希望能够使用滑块更改时间。 这在某种程度上是行不通的。 目前,代码的行为方式是,如果我快进或快退 5 秒,MP-3 会再次启动。
应用程序.js
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.scss";
import { Button, Card, Container, ProgressBar } from "react-bootstrap";
import AudioPlayer from "./components/AudioPlayer";
export default function App() {
return (
<div className="App">
<Container>
<h1>Hello CodeSandbox</h1>
<Card>
<Card.Header> Audio </Card.Header>
<Card.Body>
<AudioPlayer
audioSrc="/assets/Test_ogg_mp3_48kbps.wav.ogg"
name="Lehrpfad Audio 1"
/>
</Card.Body>
</Card>
</Container>
</div>
);
}
音频播放器
import React from "react";
import { Button, ProgressBar, InputGroup, FormControl } from "react-bootstrap";
import {
PlayCircleFill,
PauseCircleFill,
VolumeMuteFill,
VolumeDownFill,
VolumeUpFill,
} from "react-bootstrap-icons";
class AudioPlayer extends React.Component {
constructor(props) {
super(props);
this.audioRef = React.createRef();
this.audioSrc = props.audioSrc;
this.state = {
isPlaying: false,
currentTime: 0,
volume: 1, // Range between 0 and 1
progress: 0,
};
}
togglePlayPause() {
const { isPlaying } = this.state;
const audio = this.audioRef.current;
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
this.setState({ isPlaying: !isPlaying });
}
handleTimeUpdate() {
const audio = this.audioRef.current;
if (audio && !isNaN(audio.duration)) {
const progressPercentage = (audio.currentTime / audio.duration) * 100;
this.setState({ progress: progressPercentage });
if (progressPercentage >= 100) {
this.setState({ isPlaying: false, progress: 0 });
}
}
}
getVolumeIcon() {
const { volume } = this.state;
if (volume <= 0) {
return <VolumeMuteFill />;
} else if (volume > 0 && volume <= 0.5) {
return <VolumeDownFill />;
} else {
return <VolumeUpFill />;
}
}
handleVolumeChange(e) {
const newVolume = e.target.value;
this.setState({ volume: newVolume });
if (this.audioRef.current) {
this.audioRef.current.volume = newVolume;
}
}
skipTime(seconds) {
const player = document.getElementById("Player");
if (player && !isNaN(player.currentTime)) {
player.currentTime += seconds;
this.setState();
}
}
render() {
const { isPlaying, progress, volume } = this.state;
return (
<div className="container mt-5 audio-player">
<audio
id="Player"
ref={this.audioRef}
src={this.audioSrc} // Ersetze dies durch den Pfad zu deiner Audiodatei
onTimeUpdate={this.handleTimeUpdate.bind(this)}
onEnded={() => this.setState({ isPlaying: false })}
/>
<div className="d-flex align-items-center">
<Button variant="primary" onClick={() => this.skipTime(-5)}>
{" "}
-5s{" "}
</Button>
<Button
variant="primary"
onClick={this.togglePlayPause.bind(this)}
className="mx-2"
>
{isPlaying ? <PauseCircleFill /> : <PlayCircleFill />}
</Button>
<Button variant="primary" onClick={() => this.skipTime(5)}>
{" "}
+5s{" "}
</Button>
</div>
<ProgressBar
striped
variant="success"
now={progress}
label={`${Math.round(progress)}%`}
/>
<InputGroup className="mt-3">
<InputGroup.Text>{this.getVolumeIcon()}</InputGroup.Text>
<FormControl
type="range"
min="0"
max="1"
step="0.1"
value={volume}
onChange={this.handleVolumeChange.bind(this)}
/>
</InputGroup>
</div>
);
}
}
export default AudioPlayer;
我尝试了我想到的一切,但没有成功。 我确实接受一种方法会改变时间。
codesandbox.io 片段
import React from "react";
import { Button, ProgressBar, InputGroup, FormControl } from "react-bootstrap";
import {
PlayCircleFill,
PauseCircleFill,
VolumeMuteFill,
VolumeDownFill,
VolumeUpFill,
ArrowClockwise,
ArrowCounterclockwise,
} from "react-bootstrap-icons";
class AudioPlayer extends React.Component {
constructor(props) {
super(props);
this.audioRef = React.createRef();
this.audioSrc = props.audioSrc;
this.audioName = props.audioName || props.audioSrc;
this.state = {
isPlaying: false,
currentTime: 0,
volume: 1, // Range between 0 and 1
progress: 0,
};
}
togglePlayPause() {
const { isPlaying } = this.state;
const audio = this.audioRef.current;
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
this.setState({ isPlaying: !isPlaying });
}
handleTimeUpdate() {
const audio = this.audioRef.current;
if (audio && !isNaN(audio.duration)) {
const progressPercentage = (audio.currentTime / audio.duration) * 100;
this.setState({ progress: progressPercentage });
if (progressPercentage >= 100) {
this.setState({ isPlaying: false, progress: 0 });
}
}
}
getVolumeIcon() {
const { volume } = this.state;
if (volume <= 0) {
return <VolumeMuteFill />;
} else if (volume > 0 && volume <= 0.5) {
return <VolumeDownFill />;
} else {
return <VolumeUpFill />;
}
}
handleVolumeChange(e) {
const newVolume = e.target.value;
this.setState({ volume: newVolume });
if (this.audioRef.current) {
this.audioRef.current.volume = newVolume;
}
}
skipTime(seconds) {
const audio = this.audioRef.current;
if (audio && !isNaN(audio.currentTime)) {
audio.currentTime += seconds;
}
}
render() {
const { isPlaying, progress, volume } = this.state;
return (
<div className="audio-player">
<p>{this.audioName}</p>
<audio
id="Player"
ref={this.audioRef}
src={this.audioSrc} // Ersetze dies durch den Pfad zu deiner Audiodatei
onTimeUpdate={this.handleTimeUpdate.bind(this)}
onEnded={() => this.setState({ isPlaying: false })}
controls
/>
<Button
variant={isPlaying ? "danger" : "success"}
onClick={this.togglePlayPause.bind(this)}
className="playPauseBtn"
>
{isPlaying ? (
<PauseCircleFill size={80} />
) : (
<PlayCircleFill size={80} />
)}
</Button>
<div className="audio-controls">
<Button variant="primary" onClick={() => this.skipTime(-5)}>
<ArrowCounterclockwise size={50} />
-5sec
</Button>
<Button variant="primary" onClick={() => this.skipTime(5)}>
<ArrowClockwise size={50} />
+5sec
</Button>
</div>
<ProgressBar
striped
variant="success"
now={progress}
label={`${Math.round(progress)}%`}
/>
<InputGroup className="volume-input">
<InputGroup.Text>{this.getVolumeIcon()}</InputGroup.Text>
<FormControl
type="range"
min="0"
max="1"
step="0.1"
value={volume}
onChange={this.handleVolumeChange.bind(this)}
/>
</InputGroup>
</div>
);
}
}
export default AudioPlayer;