html提供的audio标签样子太固定,大部分时候我们需要自定义播放器的样式。之前没事的时候写过一个,但是只是实现了功能,没有完善。项目上用了一个大神的插件,由于没有提供源码,部分功能没法通过api实现,正好趁这个机会总结一下。
我们常用的功能无非就是播放、暂停,快进快退、音量控制,播放进度条。这里我们需要获取音频播放总时间、缓存时间、已播放时间以及音量获取设置。
使用到的方法属性如下:
-
readyState :音频加载状态,比如 0 未完成,4完成,我们所有对它的操作都应该在4以后。
-
pause() : 暂停
-
play() : 播放
-
paused : 是否暂停
-
duration : 播放总时间
-
currentTime : 已经播放的时间,这个属性可以赋值,赋值就是定位到那个时间,我们快进快退时候使用它就好
-
缓存时间获取:首先获取已缓冲部分的 TimeRanges 对象:var timeRanges = this.mp3.buffered;然后通过timeRanges.end(timeRanges.length - 1)获取缓存时间
-
volume : 音量获取设置,值在0到1之间,设置值就是调节音量大小。
具体代码
js部分(暂时没做音量控制)
import React from 'react';
import styles from './index.module.scss';
import { Progress } from 'antd';
class Mp3 extends React.Component {
constructor(){
super();
this.state = {
isPlay: false,
duration : 0, // 总时间
timeBuffered : 0, // 缓存时间
currentTime : 0, // 当前播放时间
}
}
goBack = () => {
if(this.mp3.readyState !== 4) return;
this.currentTime -= this.props.step || 15;
this.setState({currentTime : this.mp3.currentTime});
}
fastForward = () => {
if (this.mp3.readyState !== 4) return;
this.mp3.currentTime += this.props.step || 15;
this.setState({currentTime:this.mp3.currentTime});
}
pause = () =>{
if(this.mp3.readyState !== 4) return;
if(this.mp3.paused){
this.mp3.play();
this.setSate({isPlay:true});
}else{
this.mp3.pause();
this.setState({isPlay:false});
}
}
componentDidMount(){
this.mp3 = document.getElementById('myAudioComponentLiu');
// 获取缓存的时间
this.timer = setInterval(()=>{
if(this.mp3.readyState === 4){
if(this.state.duration !== this.mp3.duration){
this.setState({duration:this.mp3.duration});
}
// 获取已缓存部分的 TimeRanges 对象
var timeRanges = this.mp3.buffered;
// 获取已缓存的时间
var timeBuffered = timeRanges.end(timeRanges.length -1);
if(this.state.timeBuffered !== timeBuffered){
this.setState({timeBuffered});
}
if(this.state.currentTime !== this.mp3.currentTime){
this.setState({currentTime:this.mp3.currentTime});
}
}
},1000)
}
componentWillUnMount(){
clearInterval(this.timer);
}
setTimes = (value)=>{
let secondTime = parseInt(value);
let min = 0;
let h = 0;
let result = '';
if(secondTime > 60){
min = parseInt(secondTime / 60);
secondTime = parseInt(secondTime % 60);
if(min > 60){
h = parseInt(min / 60);
min = parseInt(min % 60);
}
}
if(min > 60){
result = `${h.toString().padStart(2,"0")}:${min.toString().padStart(2,"0")}:${secondTime.toString().padStart(2,"0")}`;;
}else{
result = `${min.toString().padStart(2,"0")}:${secondTime.toString().padStart(2,"0")}`;
}
return result;
};
render(){
let {duration,timeBuffered,currentTime,isPlay} = this.state;
// 这里可以赋值两张快进快退的默认图片
let {backImg,goImg,src} = this.props;
return (
<div className={styles.container}>
<img onClick={this.goBack} className={styles.back} src = {backImg} alt=''/>
<audio id="myAudioComponentLiu" preload="meta" src = {src} />
<div className={styles.btnBox}>
<div className={isPlay?styles.pause:styles.play} onClick={this.pause}></div>
</div>
<Progress style ={{margin:"0 0.3rem"}} showInfo={false} percent={timeBuffered / duration *100} success={{percent:currentTime/duration *100}}/>
<span className={styles.time}>
{this.setTimes(currentTime)}/{this.setTimes(duration)}
</span>
<img onClick={this.fastForward} className={styles.go} src={goImg} alt=""/>
</div>
);
}
}
export default Mp3;
css部分
.container { display: flex; align-items: center; .back,.go { cursor: pointer; flex-shrink: 0; width: 50px; user-select: none; &:hover { opacity: 0.8; } } .back { margin-right: 25px; } .go { margin-left: 25px; } .btnBox { display: flex; justify-content: center; align-items: center; width: 50px; .play { display: inline-block; cursor: pointer; border-top: 25px solid transparent; border-bottom: 25px solid transparent; border-left: 35px solid #000; margin: 0 13px; &:hover{ opacity: 0.8; } } .pause { position: relative; cursor: pointer; width: 39px; height: 50px; &::before,&::after { content: ''; position: absolute; top: 0; bottom: 0; width: 13px; background-color: #000; border-radius: 18px; } &::before { left: 0; } &::after { right: 0; } &:hover{ opacity: 0.8; } } } .time { color: #000; font-size: 25px; min-width: 214px; text-align: center; user-select: none; } :global { .ant-progress-inner { position: absolute; top: 50%; transform: translateY(-50%); background-color: #f2f7f7; .ant-progress-bg { height: 15px !important; background-color: #dfeaea; } .ant-progress-success-bg { height: 15px !important; background-color: #13bb74; } } }}
使用
-
step:number 一次快进或者快退几秒,默认是15s,非必传
-
backImg :string:快退图片地址,非必传
-
goImg : string:快进图片地址,非必传
-
src :string:音频地址,必传
import Mp3 from './components/Mp3/Mp3';
// 下边使用
<Mp3 step={5} backImg={‘快退图片’} goImg={imgUrl('快进图片')} src={'音频地址'}/>