-
Notifications
You must be signed in to change notification settings - Fork 2
/
demo.js
85 lines (77 loc) · 2.68 KB
/
demo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import React, { useState, useEffect, useRef } from 'react';
import Soundbox, { STATES } from '@nicolaz/soundbox';
import { formatTime } from '@totebox/util';
// 如果是一个音频列表组件,可将 Soundbox 实例化放在上层,并通过 props 传入
const soundbox = new Soundbox();
export default function Audio({ src, onPlaying, onError }) {
const progressRef = useRef();
const [paused, setPaused] = useState(true);
const [buffering, setBuffering] = useState(false);
const [buffered, setBuffered] = useState(0);
const [played, setPlayed] = useState(0);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0);
const [sound, setSound] = useState(null);
const [volume, setVolume] = useState(100);
const [muted, setMuted] = useState(false);
useEffect(() => {
const sound = soundbox.add({ src });
sound
.on('progress', (bufferedProgress) => {
setBuffered(bufferedProgress * 100);
})
.on('start', ({ duration }) => {
setDuration(duration);
})
.on('positionchange', (currentTime, playedProgress) => {
setCurrentTime(currentTime);
setPlayed(playedProgress * 100);
})
.on('statechange', (state) => {
setBuffering(state === STATES.BUFFERING || state === STATES.PREBUFFER);
setPaused(state !== STATES.PLAYING);
if (state === STATES.PLAYING) {
onPlaying();
}
})
.on('error', (err) => {
onError(err);
});
setSound(sound);
return () => soundbox.remove(sound);
}, [src]);
function handleProgressClick(e) {
if (sound && !paused) {
const value = (e.nativeEvent.offsetX / progressRef.current.offsetWidth).toFixed(2) * 1;
sound.setPosition(Math.floor(value * duration));
}
}
function handleVolumeChange({ target }) {
if (sound) {
setVolume(target.value)
sound.setVolume(target.value);
}
}
function handleMutedChange() {
if (sound) {
setMuted(!muted);
sound.setMute(!muted);
}
}
return (
<div className="audio">
<button className="audio-button" onClick={() => paused ? sound.play() : sound.pause()}>
{buffering ? '...' : (paused ? '|>' : '||')}
</button>
<div className="audio-duration">
{formatTime((duration - currentTime) * 1000)}
</div>
<div className="audio-progressbar" ref={progressRef} onClick={handleProgressClick}>
<span style={{ width: `${buffered}%` }}></span>
<span style={{ width: `${played}%` }}></span>
</div>
<input type="range" value={volume} onChange={handleVolumeChange} />
<span onClick={handleMutedChange}>静音</span>
</div>
);
}