1、自定义的音频播放器效果图
2、代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<style>
.img-box {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 20px 0;
}
.title {
text-align: center;
line-height: 40px;
font-size: 16px;
color: #aaa;
}
.img-rad {
display: block;
border: 10px solid #ccc;
border-radius: 50%;
}
.progress-box {
display: flex;
align-items: center;
justify-content: space-between;
}
.progress {
position: relative;
width: 250px;
height: 2px;
background: #dadada;
}
.played {
position: absolute;
width: 0;
height: 2px;
z-index: 10;
background: #ED2C28;
left: 0;
top: 0;
}
.time {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 10px;
width: 80px;
height: 20px;
border-radius: 10px;
z-index: 15;
background: #434343;
transform: translate(-40px -20px);
left: 0;
top: -9px;
}
.audio-box {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 15px 0;
}
.icon-btn {
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div id="app">
<div class="img-box">
<div class="title">周深-起风了</div>
<img class="img-rad" src="http://p1.music.126.net/LpFu9pWQ3tzldjhkLwh4Vw==/109951165291444752.jpg" width="200" height="200" alt="">
</div>
<div class="progress-box">
<div @click="changeFifteen('left')">
<img width="28" src="https://img-blog.csdnimg.cn/5258cffd0e3d4204855fb58bff908515.png" alt="">
</div>
<div ref="progress" class="progress">
<div :style="'width:' + sliderLeft + 'px'" class="played"></div>
<div class="time flex flex-item-center flex-just-center" ref="slider" id="slider" @touchstart="sliderTouchStart" @touchmove="sliderTouchMove($event)" @touchend="sliderTouchEnd" class="time absolute-container flex flex-item-center flex-just-center txt-white font10"
:style="'left:' + sliderLeft + 'px'">
<span>{{currentTime | timeFormat}}</span>/<span>{{duration | timeFormat}}</span>
</div>
</div>
<div @click="changeFifteen('right')">
<img width="28" src="https://img-blog.csdnimg.cn/7e24d2aabeb247ebbc8da8ff4369ae45.png" alt="">
</div>
</div>
<div class="audio-box">
<audio src="http://m10.music.126.net/20210904000543/c67d632954d70c2934c5c1ea1b816587/ymusic/obj/w5zDlMODwrDDiGjCn8Ky/3848922654/0b19/a863/3219/0a101cfe8374409a9219f806b445b14e.mp3" ref="audio" preload></audio>
<div>
<img width="23" src="https://img-blog.csdnimg.cn/54998c378177452f8bf9a5d66878087c.png" alt="">
</div>
<div @click="play" v-if="is_play" class="icon-btn">
<img width="65" src="https://img-blog.csdnimg.cn/6f282253d8a14cbeb19fa2031a30cf32.png" alt="">
</div>
<div @click="play" v-else class="icon-btn">
<img width="65" src="https://img-blog.csdnimg.cn/dd1bdfffd6644b43a02569562ff2e88a.png" alt="">
</div>
<div>
<img width="23" src="https://img-blog.csdnimg.cn/972679878fa843d5bf4fbd34da6b8153.png" alt="">
</div>
</div>
</div>
</body>
<script>
var start
var left
new Vue({
el: '#app',
data() {
return {
is_play: false, // 是否播放
duration: 0, // 总时长(秒)
currentTime: 0, // 已播放时长(秒)
sliderLeft: 0, // 滑块已滑动距离(已播放颜色条宽度)
slidePercent: 0, // 滑块已滑动百分比
canSlideWidth: 0, // 滑块可滑动的距离
progressWidth: 0, // 进度条的宽度
isSlide: false // 是否正在拖动
}
},
mounted: function() {
// 滑块的宽度
var sliderWidth = this.$refs.slider.offsetWidth
// 进度条的宽度
this.progressWidth = this.$refs.progress.offsetWidth
// 滑块可滑动的宽度
this.canSlideWidth = this.progressWidth - sliderWidth
// 等待之后进行赋值,避免页面渲染还没有数据的情况
setTimeout(() => {
// 获取到音频元素
var audio = this.$refs.audio;
// 设置音频的总时长
this.duration = audio.duration;
// 监听音频实时数据
audio.ontimeupdate = e => {
// 当前播放的时间(正常播放的进度)
this.currentTime = Math.floor(audio.currentTime);
// 未拖动滑块时,滑块移动的距离
if (!this.isSlide) {
// 滑块移动距离 = (已播放时长 / 总时长) * 总滑动距离
this.sliderLeft = audio.currentTime / audio.duration * this.canSlideWidth;
}
}
}, 200)
},
filters: {
// 将秒数进行格式化
timeFormat(value) {
var m = parseInt(value / 60)
var s = parseInt(value % 60)
m = m > 10 ? m : '0' + m
s = s > 10 ? s : '0' + s
return m + ':' + s
}
},
methods: {
// 控制播放/暂停
play() {
this.is_play = !this.is_play
var audio = this.$refs.audio
if (audio.paused) {
audio.play()
} else {
audio.pause()
}
},
//进度条开始拖动
sliderTouchStart(e) {
e.preventDefault();
// 修改拖动状态为正在拖动
this.isSlide = true;
// 页面宽度
var pageWidth = document.body.clientWidth;
// 触摸时滑块相对页面的位置
start = e.touches[0].pageX;
// 触摸点距滑块左边缘的距离 = 触摸时滑块相对页面的位置 - (页面宽度 - 进度条的宽度) / 2 - 滑块相对进度条左端的距离
left = start - (pageWidth - this.progressWidth) / 2 - this.$refs.slider.offsetLeft
},
sliderTouchMove(e) {
// 页面宽度
var pageWidth = document.body.clientWidth;
// 触摸点距页面左边缘的距离
var pageX = e.touches[0].pageX
// 滑动距离占进度条的百分比 = (触摸点距页面左端距离 - (页面宽度 - 进度条宽度) / 2 - 触摸点距滑块左边的相对位置) / 可滑动的总距离
var sliderLeft = (pageX - (pageWidth - this.progressWidth) / 2 - left) / this.canSlideWidth;
// 控制左右滑动不超出进度条范围(0 < 百分比 < 1)
if (sliderLeft > 1) sliderLeft = 1;
if (sliderLeft < 0) sliderLeft = 0;
// 滑块的定位left值,确定滑块位置
this.slidePercent = sliderLeft;
// 已滑动的距离(已播放颜色条宽度)
this.sliderLeft = sliderLeft * this.canSlideWidth;
},
//进度条托动放开
sliderTouchEnd() {
// 修改拖动状态为
this.isSlide = false;
var audio = this.$refs.audio;
audio.currentTime = audio.duration * this.slidePercent
},
// 快进快退15秒
changeFifteen(direction) {
var audio = this.$refs.audio
if (direction == 'left') {
audio.currentTime -= 15
} else {
audio.currentTime += 15
}
this.sliderLeft = audio.currentTime / audio.duration * this.canSlideWidth
}
}
});
</script>
</html>
3、使用说明
(1)这个效果是h5引入vue写成的
(2)封装成组件的话需要自己修改一些东西
(3)音乐链接可能已失效,请自行输入音乐链接