<template>
<div class='pro' @mouseup="mouseup" @mousemove="mousemove">
<div class='p-b'>
<div>
<a-icon type="step-backward" />
</div>
<div v-if='pause' @click="play" class='p-f'>
<a-icon type="pause" />
</div>
<div v-else @click="play" class='p-f'>
<a-icon type="caret-right" />
</div>
<div>
<a-icon type="step-forward" />
</div>
</div>
<audio ref='audio' :src="url" @timeupdate="updateTime" @canplay="getDuration"></audio>
<div class='p-p'>
<span >{{this.currentTime?this.currentTime:'00:00'}}</span>
<div @mousedown.self='clickChange'>
<!-- 进度条 -->
<!-- @mousedown.self='clickChange' -->
<div ref='progress' @mousedown.self='clickChange'></div>
<!-- 进度条上圆圈 -->
<div ref='progressBar' @mousedown="mousedown" >
<div></div>
</div>
</div>
<!-- {{$refs.audio.duration}} -->
<span v-if='this.duration'>{{this.duration}}</span>
</div>
<div class='p-v'>
<span><a-icon type="sound" /></span>
<div class='p-c'>
<div></div>
<div class='b'>
<div></div>
</div>
</div>
</div>
<div class='p-s'>
<img src="./imgs/1.png" alt="" width="180px" style='margin-top:-4px'>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name:'',
data(){
return{
pause:false,
song:'',
currentTime:'00:00',
duration:0,
url:'',
id:'',
progress:'',
progressBar:'',
x:'',
dx:'',
isMove:false,
left:'',
width:'',
progressWidth:'',
currentTimeStamp:0,
}
},
methods:{
play()
{
this.pause=!this.pause
if(this.song.paused)
{
this.song.play();
}else{
this.song.pause();
}
},
//该回调中获取duration
getDuration(e) {
this.duration = this._changeForm(this.song.duration);
},
//播放过程中调用的回调
updateTime(e) {
this.currentTime = this._changeForm(e.target.currentTime); //获取audio当前播放时间
// console.log(this.song.volume=1);
// 改变播放进度条长度
this.progress.style.width=(e.target.currentTime/this.song.duration)*400+'px';
// 改变播放进度条上圆圈位置
this.progressBar.style.left=((e.target.currentTime/this.song.duration)*400-7.5)+'px';
//在播放过程中要实时更新currentTimeStamp,否则点击抬起的事件中currentTimeStamp是拖拽/点击后的值,再次点击圆圈会回到该值
this.currentTimeStamp=e.target.currentTime;
},
//改变播放时间格式
_changeForm(time)
{
let min=Math.floor(time/60);
let seconds=Math.floor(time%60);
if(min<10)
{
min='0'+min;
}
if(seconds<10)
{
seconds='0'+seconds;
}
let timeStr=min+':'+seconds;
return timeStr;
},
//拖拽改变播放进度
mousedown(e)
{
this.x=e.clientX;
if(this.progressBar.style.left=='')
{
this.left=0;
}else{
this.left=this.delPx(this.progressBar.style.left);
}
this.isMove=true;
this.progressWidth=this.delPx(this.progress.style.width);
},
mousemove(e)
{
if(this.isMove)
{
this.dx=e.clientX;
//圆圈移动的距离=自身位移加改变的距离
let move=this.left*1+(this.dx-this.x);
move=move<=-7.5? -7.5:move;
move=move>=392.5? 392.5:move;
//进度条随移动距离而改变
let width=this.progressWidth*1+(this.dx-this.x);
width=width<=0? 0:width;
width=width>=400? 400:width;
//视图呈现
this.progressBar.style.left=move+'px';
this.progress.style.width=width+'px';
//拖动时,改变时间,不改变歌曲当前播放内容,松开时,改变歌曲播放内容
this.currentTime=this._changeForm((width/400)*this.song.duration);
this.currentTimeStamp=(width/400)*this.song.duration;
}
},
mouseup(e)
{
if(this.isMove) //只有点击进度条,松开后才会响应
{
this.isMove=false;
this.song.currentTime=this.currentTimeStamp.toFixed(2);
console.log('触发');
}
},
delPx(str)
{
return str.substring(0,str.length-2)
},
//点击改变播放,当点击按钮时,e变成按钮对象,此时获取的坐标是在按钮内的坐标
//解决方案:将点击事件分散到父元素和其他元素上,并添加.self修饰符,使得圆圈点击无效
clickChange(e)
{
//e.offsetX获取相对于当前元素的位移坐标,设置进度条和圆圈的位置
let width=e.offsetX;
let left=e.offsetX-7.5;
this.progress.style.width=width+'px';
this.progressBar.style.left=left+'px';
//改变播放内容
this.song.currentTime=(width/400)*this.song.duration.toFixed(2);
//因为还会触发鼠标抬起事件,而点击圆圈并不会触发拖动事件,会使得currentTimeStamp的值为上一次拖动结束的值
//currentTimeStamp会改变currentTime,从而使得进度条位置为上一次拖动位置
this.currentTimeStamp=(width/400)*this.song.duration.toFixed(2);
}
},
async mounted()
{
let res=await axios.get('https://api.imjad.cn/cloudmusic/?type=song&id=254485');
//设置歌曲id、播放地址、ref对象、进度条和播放进度条上圆圈
this.id=res.data.data[0].id;
this.url=res.data.data[0].url;
this.song=this.$refs.audio;
this.progress=this.$refs.progress;
this.progressBar=this.$refs.progressBar;
},
computed:{
},
watch:{
}
}
</script>
<style scoped lang='less'>
.pro{
background-color: #F6F6F8;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding:0 20px;
border: solid 1px #ccc;
.p-b{
display: flex;
align-items: center;
flex:1;
>div{
margin: 0 15px;
cursor: pointer;
}
.p-f{
height: 35px;
width: 35px;
border-radius: 35px;
text-align: center;
line-height: 35px;
background-color:#E83C3C ;
color:white;
font-size: 19px;
}
>div:first-child{
height: 30px;
width: 30px;
border-radius: 30px;
text-align: center;
line-height: 30px;
background-color:#E83C3C ;
color:white;
}
>div:last-child{
height: 30px;
width: 30px;
border-radius: 30px;
text-align: center;
line-height: 30px;
background-color:#E83C3C ;
color:white;
}
}
.p-p{
flex:3;
display:flex;
align-items: center;
margin-left: 5px;
>span{
font-size: 12px;
color:black;
margin: 0 10px;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
>div{
width: 400px;
height: 5px;
background-color: #C2C2C4;
border-radius: 5px;
position: relative;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
>div:nth-child(1){
position: absolute;
left: 0;
height: 5px;
width: 0px;
border-radius: 5px;
background-color: #E83C3C;
}
>div:nth-child(2){
position: absolute;
cursor: pointer;
left: -7.5px;
top:-5px;
height: 15px;
width: 15px;
border-radius: 10px;
border: solid 1px #ccc;
background-color: white;
display: flex;
align-items: center;
>div{
height: 5px;
width: 5px;
border-radius: 5px;
background-color:#E83C3C ;
margin: 0 auto;
}
}
>div:nth-child(2):hover{
box-shadow: #E2E2E4 0.5px 0.5px 1px 1px,#E2E2E4 -0.5px -0.5px 1px 1px
}
}
}
.p-v{
flex:1;
display: flex;
align-items: center;
>span{
margin-left: 10px;
margin-right: 5px;
}
>.p-c{
width: 100px;
height: 3px;
background-color: #C2C2C4;
border-radius: 5px;
position: relative;
// cursor: pointer;
>div:nth-child(1){
position: absolute;
left: 0;
height: 3px;
width: 50px;
border-radius: 5px;
background-color: #E83C3C;
}
>div:nth-child(2){
position: absolute;
cursor: pointer;
left: 42.5px;
top:-5px;
height: 15px;
width: 15px;
border-radius: 10px;
border: solid 1px #ccc;
background-color: white;
display: flex;
align-items: center;
display: none;
>div{
height: 5px;
width: 5px;
border-radius: 5px;
background-color:#E83C3C ;
margin: 0 auto;
}
}
}
}
.p-s{
flex:1;
cursor: pointer;
}
}
</style>
效果图: