H5的audio默认的样式可以满足我们录音播放停止等功能,提供的部分固定样式可以修改,如下:
audio::-webkit-media-controls-panel
audio::-webkit-media-controls-mute-button
audio::-webkit-media-controls-play-button
audio::-webkit-media-controls-timeline-container
audio::-webkit-media-controls-current-time-display
audio::-webkit-media-controls-time-remaining-display
audio::-webkit-media-controls-timeline
audio::-webkit-media-controls-volume-slider-container
audio::-webkit-media-controls-volume-slider
audio::-webkit-media-controls-seek-back-button
audio::-webkit-media-controls-seek-forward-button
audio::-webkit-media-controls-fullscreen-button
audio::-webkit-media-controls-rewind-button
audio::-webkit-media-controls-return-to-realtime-button
audio::-webkit-media-controls-toggle-closed-captions-button
在最新版的谷歌浏览器中,增加了播放速度。
在之前,我可以通过设置隐藏下载按钮,audio最右边的三个点就可以隐藏,现在需要把播放速度也隐藏了才可以。
我百度了很久,也没有找到播放速度的隐藏方式。
有些时候想要效果H5的audio不能满足,所以就需要自定义audio。
我要实现的效果如下:
期初:因为感觉,播放和时间可以用H5的audio,我的想法是隐藏除了播放按钮和时间显示以外的其他按钮,自己在自定义图标定位上去。
做了很多尝试,通过提供的样式api,可以隐藏进度条,喇叭,但是最右侧的三个点隐藏不了,并且,虽然按钮隐藏了,喇叭音量的滑动效果依然存在。最红还是决定自定义一个audio。
代码如下:
Audio.js
import React, {
Component } from "react";
import {
CaretRightOutlined,
PauseOutlined
} from '@ant-design/icons';
import upload from '@/assets/images/upload.png';
import deleteIcon from '@/assets/images/delete.png';
import axios from 'axios';
import styles from './index.less';
class Audio 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,
isDelete: true,
};
}
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 = (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,
});
};
// 点击下载
handleUpload = () => {
const {
record } = this.props; //录音信息
axios({
method: 'get',
url: '视频路径',
responseType: 'blob',
headers: {
'content-type': 'audio/mpeg' }
}).then((res) => {
let blobType = 'application/force-download' // 设置blob请求头
let blob = new Blob([res.data], {
type: res.data.type }) // 创建blob 设置blob文件类型 data 设置为后端返回的文件(例如mp3,jpeg) type:这里设置后端返回的类型 为 mp3
let downa = document.createElement('a') // 创建A标签
let href = window.URL.createObjectURL(blob) // 创建下载的链接
downa.href = href // 下载地址
downa.download = record.name || '音频' // 下载文件名
document.body.appendChild(downa)
downa.click() // 模拟点击A标签
document.body.removeChild(downa) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放blob对象
}).catch(function (error) {
console.log(error)
})
};
deleteAudio = () => {
const {
id } = this.props;
const audio = document.getElementById(`audio${
id}`);
// audio.pause();
this.setState({
isDelete: false,
});
this.props.onClick();
};
render() {
const {
src, id, type,bg} = this.props;
const {
isPlay,
isMuted,
volume,
allTime,
currentTime,
rateList,
playRate,
isDelete
} = this.state;
return (
<div >
<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>
{
isDelete && <div className={
type === 'delete' ? styles.audio_delete : styles.audio_style} style={
{
background: bg}}>
<div className={
styles.audio_left}>
{
isPlay ? (
<span onClick={
this.pauseAudio}><PauseOutlined className={
styles.audio_play}/></span>
) : (
<span onClick={
this.playAudio} > <CaretRightOutlined className={
styles.audio_play}/></span>
)}
<span className={
styles.audio_time}>
{
this.formatSecond(currentTime) + "/" + this.formatSecond(allTime)}
</span>
</div>
{
type === "delete" ? <img src={
deleteIcon} onClick={
this.deleteAudio} className={
styles.download} /> : <img src={
upload} onClick={
this.handleUpload} className={
styles.download} />
}
</div>
}
</div>
);
}
}
export default Audio;
index.less
.audio_delete,
.audio_style {
width: 192px;
background: #FFECE5;
// background: #F2F3F5;
border-radius: 4px;
font-weight: 400;
text-align: center;
cursor: pointer;
padding: 0 12px;
display: flex;
justify-content: space-between;
align-items: center;
.download {
width: 16px;
height: 16px;
}
.audio_left {
display: inline-block;
.audio_time {
margin-left: 12px;
color: #5E5E66;
}
}
}
.audio_style {
height: 32px;
line-height: 32px;
font-size: 12px;
.audio_play{
font-size: 14px;
}
}
.audio_delete {
height: 56px;
line-height: 56px;
font-size: 14px;
.audio_play{
font-size: 16px;
}
}