1景鼠、自定義的音頻播放器效果圖
music.jpeg
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">周深-起風(fēng)了</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, // 總時(shí)長(zhǎng)(秒)
currentTime: 0, // 已播放時(shí)長(zhǎng)(秒)
sliderLeft: 0, // 滑塊已滑動(dòng)距離(已播放顏色條寬度)
slidePercent: 0, // 滑塊已滑動(dòng)百分比
canSlideWidth: 0, // 滑塊可滑動(dòng)的距離
progressWidth: 0, // 進(jìn)度條的寬度
isSlide: false // 是否正在拖動(dòng)
}
},
mounted: function() {
// 滑塊的寬度
var sliderWidth = this.$refs.slider.offsetWidth
// 進(jìn)度條的寬度
this.progressWidth = this.$refs.progress.offsetWidth
// 滑塊可滑動(dòng)的寬度
this.canSlideWidth = this.progressWidth - sliderWidth
// 等待之后進(jìn)行賦值油额,避免頁(yè)面渲染還沒有數(shù)據(jù)的情況
setTimeout(() => {
// 獲取到音頻元素
var audio = this.$refs.audio;
// 設(shè)置音頻的總時(shí)長(zhǎng)
this.duration = audio.duration;
// 監(jiān)聽音頻實(shí)時(shí)數(shù)據(jù)
audio.ontimeupdate = e => {
// 當(dāng)前播放的時(shí)間(正常播放的進(jìn)度)
this.currentTime = Math.floor(audio.currentTime);
// 未拖動(dòng)滑塊時(shí)催植,滑塊移動(dòng)的距離
if (!this.isSlide) {
// 滑塊移動(dòng)距離 = (已播放時(shí)長(zhǎng) / 總時(shí)長(zhǎng)) * 總滑動(dòng)距離
this.sliderLeft = audio.currentTime / audio.duration * this.canSlideWidth;
}
}
}, 200)
},
filters: {
// 將秒數(shù)進(jìn)行格式化
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()
}
},
//進(jìn)度條開始拖動(dòng)
sliderTouchStart(e) {
e.preventDefault();
// 修改拖動(dòng)狀態(tài)為正在拖動(dòng)
this.isSlide = true;
// 頁(yè)面寬度
var pageWidth = document.body.clientWidth;
// 觸摸時(shí)滑塊相對(duì)頁(yè)面的位置
start = e.touches[0].pageX;
// 觸摸點(diǎn)距滑塊左邊緣的距離 = 觸摸時(shí)滑塊相對(duì)頁(yè)面的位置 - (頁(yè)面寬度 - 進(jìn)度條的寬度) / 2 - 滑塊相對(duì)進(jìn)度條左端的距離
left = start - (pageWidth - this.progressWidth) / 2 - this.$refs.slider.offsetLeft
},
sliderTouchMove(e) {
// 頁(yè)面寬度
var pageWidth = document.body.clientWidth;
// 觸摸點(diǎn)距頁(yè)面左邊緣的距離
var pageX = e.touches[0].pageX
// 滑動(dòng)距離占進(jìn)度條的百分比 = (觸摸點(diǎn)距頁(yè)面左端距離 - (頁(yè)面寬度 - 進(jìn)度條寬度) / 2 - 觸摸點(diǎn)距滑塊左邊的相對(duì)位置) / 可滑動(dòng)的總距離
var sliderLeft = (pageX - (pageWidth - this.progressWidth) / 2 - left) / this.canSlideWidth;
// 控制左右滑動(dòng)不超出進(jìn)度條范圍(0 < 百分比 < 1)
if (sliderLeft > 1) sliderLeft = 1;
if (sliderLeft < 0) sliderLeft = 0;
// 滑塊的定位left值肮蛹,確定滑塊位置
this.slidePercent = sliderLeft;
// 已滑動(dòng)的距離(已播放顏色條寬度)
this.sliderLeft = sliderLeft * this.canSlideWidth;
},
//進(jìn)度條托動(dòng)放開
sliderTouchEnd() {
// 修改拖動(dòng)狀態(tài)為
this.isSlide = false;
var audio = this.$refs.audio;
audio.currentTime = audio.duration * this.slidePercent
},
// 快進(jìn)快退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勺择、使用說(shuō)明
(1)這個(gè)效果是h5引入vue寫成的
(2)封裝成組件的話需要自己修改一些東西
(3)音樂(lè)鏈接可能已失效,請(qǐng)自行輸入音樂(lè)鏈接
4伦忠、用到的圖片
left15.png
right15.png
played.png
paused.png
last.png
next.png