为了满足产品的需求,为了实现多种浏览器音频播放器的样式保持一直,动手封装一个简单的播放组件
功能和效果
- 时长
- 播放进度条
- 倍速
- 调音
- 暂停播放
- 点击下载
效果如下,可以根据自己的需要更改样式
注意事项
- 若是单页面应用,切换页面时,应该暂停当然audio的播放
引入组件使用
<AudioPlay
id="record"
src={http:xxx.mp3}
></AudioPlay>
根据URL实现下载文件的工具方法
import { message } from "antd";
const lyh = {}
lyh.downUrl = (fileName, url) => {
message.info("正在下载中...");
let x = new XMLHttpRequest();
x.open("GET", url, true);
x.responseType = "blob";
x.onload = function(e) {
let blob = x.response;
if ("msSaveOrOpenBlob" in navigator) {
//IE导出
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
let a = document.createElement("a");
a.download = fileName;
a.href = URL.createObjectURL(blob);
document.querySelector("body").appendChild(a);
a.click();
document.querySelector("body").removeChild(a);
message.info("下载成功");
}
};
x.send();
};
export default lyh;
react组件代码-AudioPlay.js
import React, { Component } from "react";
import "./style/audio.less";
import lyh from "../../../../lib/lyh";
import { Input, Icon, Dropdown, Menu, Button, Slider } from "antd";
class App 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);
let minite = Math.floor(time / 60);
return `${minite}:${second >= 10 ? second : `0${second}`}`;
}
// 该视频已准备好开始播放
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
});
}
};
changeVolume = value => {
const { id } = this.props;
const audio = document.getElementById(`audio${id}`);
audio.volume = value / 100;
this.setState({
volume: value,
isMuted: !value
});
};
onChangeMutedStatus = a => {
const { id } = this.props;
const audio = document.getElementById(`audio${id}`);
this.setState({
isMuted: !audio.muted
});
audio.muted = !audio.muted;
};
// 倍速播放
changePlayRate = ({ item, key, keyPath, domEvent }) => {
this.audioDom.playbackRate = key;
this.setState({
playRate: key
});
};
render() {
const { src, id } = this.props;
const {
isPlay,
isMuted,
volume,
allTime,
currentTime,
rateList,
playRate
} = this.state;
return (
<div className="lyh-audio-wrap">
<span className="lyh-audio-voice">
<i className="lyh-audio-first" />
<i className="lyh-audio-second" />
<i className="lyh-audio-three" />
<i className="lyh-audio-four" />
<i className="lyh-audio-first" />
<i className="lyh-audio-second" />
<i className="lyh-audio-three" />
<i className="lyh-audio-four" />
<i className="lyh-audio-first" />
<i className="lyh-audio-second" />
<i className="lyh-audio-three" />
<i className="lyh-audio-four" />
<i className="lyh-audio-first" />
<i className="lyh-audio-second" />
<i className="lyh-audio-three" />
<i className="lyh-audio-four" />
<i className="lyh-audio-first" />
<i className="lyh-audio-second" />
<i className="lyh-audio-three" />
<i className="lyh-audio-four" />
</span>
<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>
<div className="audio-control-wrap lyh-fsb">
<span>
{this.formatSecond(currentTime) + "/" + this.formatSecond(allTime)}
</span>
<input
type="range"
step="0.01"
max={allTime}
value={currentTime}
onChange={this.changeTime}
style={{ flex: 1, margin: "0 10px" }}
/>
<div className="audio-control lyh-fsb" style={{ width: 122 }}>
<Dropdown
overlay={
<Menu onClick={this.changePlayRate}>
{rateList.map(v => (
<Menu.Item key={v}>{v}x</Menu.Item>
))}
</Menu>
}
placement="topCenter"
>
<div
style={{
cursor: "pointer"
// width: 22
}}
>
{playRate}x
</div>
</Dropdown>
<Dropdown
overlay={
<div
style={{
display: "inline-block",
height: 66,
paddingBottom: 8
}}
>
<Slider
vertical
onChange={this.changeVolume}
value={isMuted ? 0 : volume}
/>
</div>
}
placement="topCenter"
>
<div
className="soud-wrap lyh-fjic"
onClick={this.onChangeMutedStatus}
>
<Icon type="sound" className="ico" />
{isMuted ? <div className="muted-ico"></div> : ""}
</div>
</Dropdown>
{isPlay ? (
// theme="twoTone"
<Icon
type="pause-circle"
className="ico"
onClick={this.pauseAudio}
/>
) : (
<Icon
type="play-circle"
className="ico"
onClick={this.playAudio}
/>
)}
<Icon
type="download"
className="ico"
onClick={a => lyh.downUrl("通话录音", src)}
/>
</div>
</div>
</div>
);
}
}
export default App;
audio.less样式文件
.audio-control-wrap {
.ico {
font-size: 18px;
cursor: pointer;
}
.soud-wrap {
width: 20px;
height: 20px;
position: relative;
.muted-ico {
position: absolute;
top: 0;
left: 10px;
width: 2px;
height: 100%;
background-color: #272525;
transform: rotate(130deg);
z-index: 99;
}
}
}
.lyh-audio-voice {
display: flex;
align-items: flex-end;
justify-content: center;
height: 100%;
height: 15px;
height: 38px;
i {
display: inline-block;
border-left: 2px solid #10ea14;
margin: 0 1px;
position: relative;
&.lyh-audio-first {
height: 8px;
height: 24px;
animation: first 0.5s linear 0s infinite alternate;
}
&.lyh-audio-second {
height: 4px;
height: 12px;
animation: second 1s linear 0s infinite alternate;
}
&.lyh-audio-three {
height: 6px;
height: 18px;
animation: three 0.8s linear 0s infinite alternate;
}
&.lyh-audio-four {
height: 12px;
height: 36px;
animation: four 0.6s linear 0s infinite alternate;
}
}
@keyframes first {
0% {
height: 4px;
}
50% {
height: 8px;
}
100% {
height: 10px;
}
}
@keyframes second {
0% {
height: 12px;
}
50% {
height: 9px;
}
100% {
height: 7px;
}
}
@keyframes three {
0% {
height: 14px;
height: 24px;
}
50% {
height: 12px;
height: 32px;
}
100% {
height: 10px;
height: 20px;
}
}
@keyframes four {
0% {
height: 10px;
height: 30px;
}
50% {
height: 8px;
height: 24px;
}
100% {
height: 5px;
height: 15px;
}
}
}