import Audio from "./AudioPlay";
<Audio
src={
"https://xxx.mp3"
}
id={123}
/>
import React, {Component} from 'react';
import {Popover} from 'antd';
import moment from 'moment';
import style from './style.less';
import playAudio from '../../../images/player.png';
import pauseAudio from '../../../images/icon_play_stop.png';
import onMuteAudio from '../../../images/mute.png';
import onNoMuteAudio from '../../../images/no-mute.png';
import download from '../../../images/download.png';
class index extends Component {
constructor(props) {
super(props);
this.state = {
rateList: [1.0, 1.25, 1.5, 2.0],
playRate: 1.0,
isPlay: false,
isMuted: false,
volume: 100,
allTime: 0,
currentTime: 0
};
}
componentDidMount() {}
formatSecond(time) {
const second = Math.floor(time % 60);
const minite = Math.floor(time / 60);
return `${minite}:${second >= 10 ? second : `0${second}`}`;
}
handleDownloadClick = () => {
if (!this.props.src) return;
const url = this.props.src;
let request;
const ishttps = document.location.protocol == 'https:';
if (ishttps && url) {
url.split('://');
request = `https://${url.split('://')[1]}`;
} else {
request = url;
}
const text = `${this.props.DownloadName}.wav`;
this.courseDownload(request, text);
};
// 实现js下载文件修改文件名失效问题 start
courseDownload = (url, filename) => {
const that = this;
this.getBlob(url, function (blob) {
that.saveAs(blob, filename);
});
};
getBlob = (url, cb) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (xhr.status === 200) {
cb(xhr.response);
}
};
xhr.send();
};
/**
* 保存
* @param {Blob} blob
* @param {String} filename 想要保存的文件名称
*/
saveAs = (blob, filename) => {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
const body = document.querySelector('body');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// fix Firefox
link.style.display = 'none';
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
};
// 该视频已准备好开始播放
onCanPlay = () => {
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
this.setState({
allTime: audio.duration
});
};
playAudio = () => {
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
audio.play();
this.setState({
isPlay: true
});
};
pauseAudio = () => {
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
audio.pause();
this.setState({
isPlay: false
});
};
onMuteAudio = () => {
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
this.setState({
isMuted: !audio.muted
});
audio.muted = !audio.muted;
};
changeTime = e => {
const {value} = e.target;
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
this.setState({
currentTime: value
});
audio.currentTime = value;
if (value === audio.duration) {
this.setState({
isPlay: false
});
}
};
// 当前播放位置改变时执行
onTimeUpdate = () => {
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
this.setState({
currentTime: audio.currentTime
});
if (audio.currentTime === audio.duration) {
this.setState({
isPlay: false
});
}
const progressTime = (100 * this.state.currentTime) / audio.duration;
this.inputDom.style.background = `linear-gradient(to right, #007cef 0%, #007cef ${parseInt(progressTime, 10)}%, transparent ${parseInt(progressTime, 10)}%, transparent 100%)`;
if (audio.currentTime === audio.duration) {
this.setState({
isPlay: false
});
this.inputDom.style.background = `linear-gradient(to right, #007cef 0%, #007cef 100%, transparent 100%, transparent 100%)`;
}
};
changeVolume = e => {
const {value} = e.target;
const {id} = this.props;
const audio = document.getElementById(`audio${id}`);
audio.volume = value / 100;
this.setState({
volume: value,
isMuted: !value
});
};
// 倍速播放
changePlayRate = num => {
this.audioDom.playbackRate = num;
this.setState({
playRate: num
});
};
render() {
const {src, id} = this.props;
// const {isPlay, isMuted, volume, allTime, currentTime, rateList, playRate} = this.state;//倍数
const {isPlay, isMuted, volume, allTime, currentTime} = this.state;
return (
<div className={style.AudioComponent}>
<audio
id={`audio${id}`}
src={src}
ref={audio => {
this.audioDom = audio;
}}
preload={'auto'}
onCanPlay={this.onCanPlay}
onTimeUpdate={this.onTimeUpdate}>
<track src={src} kind="captions" />
</audio>
{isPlay ? (
<div className={style.isPlayBox} onClick={this.pauseAudio}>
<img src={pauseAudio} />
</div>
) : (
<div className={style.isPlayBox} onClick={this.playAudio}>
<img src={playAudio} />
</div>
)}
<div className={style.audioInputBox}>
<div className={style.AudioBox}>
<input className={style.AudioInput} ref={dom => (this.inputDom = dom)} type="range" step="0.01" max={allTime} value={currentTime} onChange={this.changeTime} />
</div>
<span className={style.timeBox}>{`${this.formatSecond(currentTime)}/${this.formatSecond(allTime)}`}</span>
</div>
<div className={style.volumeBox}>
<Popover
overlayClassName={'volumeBox'}
trigger="click"
content={
<div className="volume">
<div onClick={this.onMuteAudio}>
<img src={!isMuted ? onMuteAudio : onNoMuteAudio} />
</div>
<input type="range" onChange={this.changeVolume} value={isMuted ? 0 : volume} />
</div>
}>
<span>
<img src={onNoMuteAudio} />
</span>
</Popover>
</div>
<div onClick={this.handleDownloadClick}>
<img src={download} alt="" />
</div>
{/* <div>
<span>倍速播放:</span>
{rateList &&
rateList.length > 0 &&
rateList.map(item => (
<button
key={item}
style={
playRate === item
? {
border: '1px solid #188eff',
color: '#188eff'
}
: null
}
onClick={() => this.changePlayRate(item)}>
{item}
</button>
))}
</div> */}
</div>
);
}
}
export default index;
.AudioComponent {
display: flex;
align-items: center;
background-color: #fff;
width: 100%;
max-width: 500px;
height: 32px;
padding: 20px;
border-radius: 16px;
> div {
margin-right: 12px;
&:last-child {
margin-right: 0;
}
}
.content {
display: flex;
justify-content: center;
align-items: center;
}
.timeBox {
font-size: 12px;
font-weight: 400;
color: #bababa;
margin-left: 4px;
}
.isPlayBox {
img {
width: 20px;
height: 20px;
.content;
}
}
.audioInputBox {
display: flex;
align-items: center;
}
.AudioBox {
background-color: #dfdfdf;
position: relative;
height: 8px;
border-radius: 4px;
overflow: hidden;
width: 200px;
.AudioInput {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: linear-gradient(to right, #007cef, transparent 0%, transparent);
background-size: 100% 100%;
&[type='range'] {
width: 100%;
-webkit-appearance: none;
height: 8px;
border-radius: 4px;
background: -webkit-linear-gradient(#007cef, #007cef) no-repeat transparent;
background-size: 0% 100%; /* 因为周期默认value=0.50正好占50% */
}
&[type='range']::-webkit-slider-thumb:hover {
background-color: transparent;
}
&[type='range']::-webkit-slider-runnable-track {
border-radius: 10px; /*将轨道设为圆角的*/
}
&[type='range']::-webkit-slider-thumb {
position: relative;
left: -16px;
-webkit-appearance: none;
background-color: #007cef;
width: 16px;
height: 8px;
cursor: pointer;
}
}
}
}
:global {
.volumeBox {
// transform: rotate(-90deg);
// .ant-popover-arrow-content {
// display: none;
// }
.ant-popover-inner-content {
padding: 0 16px;
}
.volume {
display: flex;
> div {
padding: 5px;
}
}
}
}