Technology stack used (Vue3.0 +typeScript+Element Plus)
Packaging as components is recommended for use in existing projects. Vue2. X can be modified to not support TS, you can remove the related type judgment, you need different styles, you can define your own styles
H5 Audio Related events and attributes
<audio
ref="audio"
class="audioStyle"
:src="url"
:preload="audioState.preload"
@play="onPlay"
@error="onError"
@waiting="onWaiting"
@pause="onPause"
@timeupdate="onTimeupdate"
@loadedmetadata="onLoadedmetadata"
>
</audio>
Copy the code
1.SRC is the address of the audio2.The preload attribute specifies whether audio is loaded after the page is loaded - Auto loads the entire audio after the page is loaded - Meta loads only metadata after the page is loaded - None loads no audio after the page is loaded3.OnPlay Play method4.OnPause Pause method5.OnTimeupdate The progress bar can also be updated when the timeUpdate event is used to update the current playback time of the audio stream approximately once per second6.Loadedmetadata Duration for loading audio filesCopy the code
Define the styles and methods used to play recordings
1.OnLoadedmetadata is used to load the audioconst onLoadedmetadata = (res) = > {
state.audioState.waiting = false
state.audioState.maxTime = parseInt(res.target.duration)
}
2.Click the pause or play button to invoke audio's corresponding functionconst audio = ref(); // Vue3. X is not written here
const startPlayOrPause=() = > {
return state.audioState.playing ? pausePlay() : startPlay()
}
// Start playing
const startPlay =() = > {
audio.value.play()
}
/ / pause
const pausePlay = () = > {
audio.value.pause()
}
3.Drag the progress bar to update the playback time in real time// Play jump
const changeCurrentTime = (index) = > {
audio.value.currentTime = Math.floor((index) / 100 * state.audioState.maxTime))
}
4.Change the volume// The volume is changed through audio's volume property
const changeVolume = (index = 0) = > {
audio.value.volume = Number(index) / 100
state.volume = index
}
5.Downloading recording Filesconst downloadFile=() = >{
let temurl=state.url.split('. ').slice(-2) [0].split('/').slice(-1) [0]
var laststr=temurl.lastIndexOf('_');
var newStr=temurl.substring(0,laststr);
let itemName=newStr
download(state.url,itemName)
}
const download =(url, filename) = > {
url=url+`?The ${Math.random()}`
getBlob(url, function(blob:any) { saveAs(blob, filename); })}const getBlob=(url:String,cb:any) = > {
var xhr:any = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (xhr.status === 200) { cb(xhr.response); }}; xhr.send(); }const saveAs=(blob, filename) = > {
var link:any = document.createElement('a');
var body:any = 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);
}
6.Fast forward by modifying audio's playbackRate propertyconst changeSpeed =() = > {
let index = state.speeds.indexOf(state.audioState.speed) + 1
state.audioState.speed = state.speeds[index % state.speeds.length]
audio.value.playbackRate = state.audioState.speed
}
Copy the code
The complete code
<template>
<div class="audio_player">
<audio
ref="audio"
class="audioStyle"
:src="url"
:preload="audioState.preload"
@play="onPlay"
@error="onError"
@waiting="onWaiting"
@pause="onPause"
@timeupdate="onTimeupdate"
@loadedmetadata="onLoadedmetadata"
>
</audio>
<! -- Function configuration menu function off -->
<div class="playevent">
<! -- Pause play -->
<el-image
class="hoverClass"
@click="startPlayOrPause"
style="width: 30px; height: 30px"
:src="playStatusurlArr[audioState.playing]"
fit="scale-down"
>
</el-image>
<div class="split_style"></div>
<! Fast forward can be configured to disable -->
<el-button
v-if="false"
type="text"
@click="changeSpeed">{{' fast forward: x' + Audiostate.speed}}</el-button>
<el-button
type="text"
style="color:#909399;">{{ realFormatSecond(audioState.currentTime)}}
</el-button>
<div class="content_solid">
<el-slider
class="slider"
v-model="sliderTime"
:format-tooltip="formatProcessToolTip"
@change="changeCurrentTime" >
</el-slider>
</div>
<el-button type="text" style="color:#909399;">
{{realFormatSecond(audioState.maxTime)}}
</el-button>
<div class="split_style"></div>
<! -- Mute function can be configured function off -->
<el-button
v-if="false" type="text"
@click="startMutedOrNot">{{audioState.muted ? 'Play' : 'mute '}}</el-button>
<div class="voice_solid">
<el-image
@click="moreMiniVoice"
class="hoverClass"
style="width: 30px; height: 30px; margin-right:8px;"
:src="playStatusurlArr['sound']"
fit="scale-down"
>
</el-image>
<el-slider
class="sliderVoice"
v-model="volume"
:format-tooltip="formatVolumeToolTip"
@change="changeVolume" >
</el-slider>
<el-image
@click="moreMaxVoice"
class="hoverClass"
style="width: 30px; height: 30px"
:src="playStatusurlArr['moresound']"
fit="scale-down"
>
</el-image>
</div>
<div class="split_style" style="margin-right: 12px;"></div>
<! - download - >
<el-image
class="hoverClass"
@click="downloadFile"
style="width: 30px; height: 30px"
:src="playStatusurlArr['download']"
fit="scale-down"
>
</el-image>
</div>
</div>
</template>
<script lang="ts">
import { onMounted, reactive, toRefs, ref } from 'vue';
export default {
name: 'audioPlayer'.props: {
theUrl: {
type: String.required: true,},theSpeeds: {
type: Array.default () {
return [1.1.5.2]}},theControlList: {
type: String.default: ' '}},setup(props:any, ctx:any) {
const state=reactive({
url: props.theUrl,
audioState: {
currentTime: 0.maxTime: 0.playing: false.muted: false.speed: 1.waiting: true.preload: 'auto'
},
sliderTime: 0.volume: 50.speeds: props.theSpeeds,
/** * Control function data */
controlList: {
// You can configure the passed parameter to display the specific function
},
// You need to configure your own image effects here
playStatusurlArr: {false:' '.true:' '.'download':' '.'sound':' '.'moresound':' ',
}
})
setControlList()
// When the audio starts playing
const onPlay = (res:any) = > {
state.audioState.playing = true
if(! state.controlList.onlyOnePlaying){return
}
let target = res.target
let audios = document.getElementsByTagName('audio');
[...audios].forEach((item) = > {
if(item ! == target){ item.pause() } }) }// When an error occurs, the loading state is loaded
const onError = () = > {
state.audioState.waiting = true
}
// When the audio starts to wait
const onWaiting = (res:any) = > {
console.log(res)
}
// When audio pauses
const onPause = () = > {
state.audioState.playing = false
}
// When a timeUpdate event occurs approximately once per second, it is used to update the current playback time of the audio stream
const onTimeupdate =(res:any) = > {
state.audioState.currentTime = res.target.currentTime
state.sliderTime = Math.floor(Number(state.audioState.currentTime) / Number(state.audioState.maxTime) * 100)}const onLoadedmetadata = (res:any) = > {
state.audioState.waiting = false
state.audioState.maxTime = parseInt(res.target.duration)
}
/** * the following is the button trigger event */
const audio = ref();
const startPlayOrPause=() = > {
return state.audioState.playing ? pausePlay() : startPlay()
}
// Start playing
const startPlay =() = > {
audio.value.play()
}
/ / pause
const pausePlay = () = > {
audio.value.pause()
}
const changeSpeed =() = > {
let index = state.speeds.indexOf(state.audioState.speed) + 1
state.audioState.speed = state.speeds[index % state.speeds.length]
audio.value.playbackRate = state.audioState.speed
}
const realFormatSecond=(second:any) = > {
var secondType = typeof second
if (secondType === 'number' || secondType === 'string') {
second = parseInt(second)
var hours = Math.floor(second / 3600)
second = second - hours * 3600
var mimute = Math.floor(second / 60)
second = second - mimute * 60
return hours + ':' + ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)}else {
return '0:00:00'}}// Progress bar toolTip
const formatProcessToolTip =(index = 0) = > {
index =Math.floor(Number(state.audioState.maxTime) / 100 * index)
return 'Progress bar:' + realFormatSecond(index)
}
// Play jump
const changeCurrentTime = (index:any) = > {
audio.value.currentTime = Math.floor(Number(index) / 100 * Number( state.audioState.maxTime))
}
const startMutedOrNot =() = >{ audio.value.muted = ! audio.value.muted audio.value.muted = audio.value.muted }// Volume bar toolTip
const formatVolumeToolTip=(index:any) = > {
return 'Volume bar:' + index
}
// The volume changes
const changeVolume = (index:any = 0) = > {
audio.value.volume = Number(index) / 100
state.volume = index
}
const moreMiniVoice =() = >{
audio.value.volume = 0
state.volume = 0
}
const moreMaxVoice =() = >{
audio.value.volume = 1
state.volume = 100
}
// Download the file
const downloadFile=() = >{
let temurl=state.url.split('. ').slice(-2) [0].split('/').slice(-1) [0]
var laststr=temurl.lastIndexOf('_');
var newStr=temurl.substring(0,laststr);
let itemName=newStr
download(state.url,itemName)
}
const download =(url:any, filename:String) = > {
url=url+`?The ${Math.random()}`
getBlob(url, function(blob:any) { saveAs(blob, filename); })}const getBlob=(url:String,cb:any) = > {
var xhr:any = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (xhr.status === 200) { cb(xhr.response); }}; xhr.send(); }const saveAs=(blob:any, filename:any) = > {
var link:any = document.createElement('a');
var body:any = 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);
}
onMounted(() = > {
// Automatically play when clicked
// startPlayOrPause()
})
return {
...toRefs(state),
onPlay,
onError,
onWaiting,
onPause,
onTimeupdate,
onLoadedmetadata,
startPlayOrPause,
audio,
changeSpeed,
realFormatSecond,
formatProcessToolTip,
changeCurrentTime,
startMutedOrNot,
formatVolumeToolTip,
changeVolume,
setControlList,
downloadFile,
download,
getBlob,
saveAs,
moreMiniVoice,
moreMaxVoice,
}
}
}
</script>
<style scope>
.audio_player {
display: inline-block;
padding:4px 16px 4px 16px;
border-radius: 4px;
}
.audioStyle {
display: none;
}
.slider {
display: inline-block;
width: 190px;
margin: 0 15px ;
margin-top: 4px;
}
.sliderVoice {
display: inline-block;
width: 100px;
margin-right:16px;
}
.download {
color: #409EFF;
margin-left: 15px;
}
.playevent {
display: flex;
align-items: center;
justify-content: center;
}
.split_style {
border-left:1px solid #DCDFE6;
height:38px;
margin:0 16px;
width: 1px;
}
.hoverClass:hover {
cursor: pointer;
}
</style>
<style>
.audio_player .el-button {
display: inline-block;
line-height: 1;
min-height: 24px;
padding:0;
}
.audio_player .el-dialog__header {
padding: 0;
border-bottom:none;
}
.content_solid .el-slider__button {
display: inline-block;
width: 10px;
height: 10px;
vertical-align: middle;
border: 1px solid #025BAC;
border-radius: 50%;
box-sizing: border-box;
box-shadow: 0px 0px 6px 0px rgba(0.0.0.0.3);
transition:.1s;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background:#025BAC;
}
.voice_solid .el-slider__button {
width: 16px;
height: 16px;
background: #FFFFFF;
border: 1px solid #fff;
box-shadow: 0px 0px 6px 0px rgba(0.0.0.0.3);
}
.voice_solid {
display:flex;
align-items:center;
}
</style>
Copy the code
The above is all the components in the code recommended all copy for testing and modification
Define the components
Using the component
Component and the cords