使⽤vue实现⾃⼰⾳乐播放器仿⽹易云移动端(audio、播放、暂停、上⼀⾸、
下⼀⾸、展⽰评。。。
最终实现成果展⽰
1.播放暂停功能的实现
这是audio标签
<audio @timeupdate="updateTime"@canplay="getDuration"@ended="ended":src="musicUrl"ref="audio"></audio>
这是播放和暂停图标
<div class="pause"v-show="isPlaying"@click="pauseSong"><i class="fa fa-pause"></i></div>
<div class="play"v-show="!isPlaying"@click="playSong"><i class="fa fa-play"></i></div>
播放和暂停事件我们通过 this.$refs.audio.play()和this.$refs.audio.pause()来进⾏控制,并切换isPlaying的值来改变图标的显⽰。设置this.$refs.audio.autoplay= true 可实现歌曲⾃动播放
中间圆形图⽚的旋转和暂停是通过添加类名控制:
css样式如下:
.
animation: rotateIMG 15s linear infinite;
}
.cd.rotatePause img{
animation-play-state:paused;
-webkit-animation-play-state:paused;/* Safari 和 Chrome */
}
@keyframes rotateIMG{
from{
transform:rotate(0deg);
}
to{
transform:rotate(360deg);
}
}
html结构如下:
<div class="cd"v-show="show"@click="show = !show"ref="cd">
<img :src="playingSong.blurPicUrl"width="60%">
</div>
js控制如下:
// 播放时
this.$refs.cd.classList.add('rotate')
if(this.$refs.ains('rotatePause'))this.$refs.ve('rotatePause')
// 暂停时
this.$refs.cd.classList.add('rotatePause')
2. 上⼀⾸下⼀⾸功能的实现
要实现这个功能我们就要拿到当前歌曲列表的所有数据。我请求的是⽹易云的接⼝,将数据存在vuex⾥⾯。我们只需通过切换数组索引即可达到切换歌曲。
歌曲列表是通过遍历出来的,所以我们可以给节点加上data-index属性。结果像下⾯这样
接下来点击的时候我们把当前data-index存到localStorage⾥⾯,之后在上⼀⾸/下⼀⾸的点击事件⾥ – 或者 ++进⾏切换,并做边界值判断 代码如下:
prevSong(){// 播放上⼀⾸歌曲
localStorage.curSongPlayIndex--
if(localStorage.curSongPlayIndex <0) localStorage.curSongPlayIndex =this.$store.state.songPlayList.length -1
this.playingSong =this.$store.state.songPlayList[JSON.parse(localStorage.curSongPlayIndex)]
this.loadMusic()// 加载⾳乐地址加载歌词加载喜欢状态加载⾳乐评论
this.autoPlaySong()// 点击之后歌曲或⾃动播放
}
3.进度条显⽰时间显⽰进度条拖拽功能实现
3.1获取⾳乐总时长
在canplay钩⼦函数拿到总时长
getDuration(){// canplay时获取⾳频总时长
this.duration =this.$refs.audio.duration
this.allTime =this.formatTime(this.$refs.audio.duration)
},
注意:时间获取出来是秒。我们要显⽰的是mm:ss格式。所以 this.duration存的时间是秒 this.allTime存的时间是格式化之后的formatTime函数代码如下:
formatTime(time){
if(time ===0){
this.curTime ='00:00'
return
}
const mins = Math.floor(time /60)<10?`0${Math.floor(time /60)}`: Math.floor(time /60)
const sec = Math.floor(time %60)<10?`0${Math.floor(time %60)}`: Math.floor(time %60)
return`${mins}:${sec}`
}
3.2拿到当前时间更新进度条
在timeupdate钩⼦函数获取当前播放时间
updateTime(e){// timeupdate时获取当前播放时间
const{ currentTime }= e.target
this.currentTime = currentTime
this.curTime =this.formatTime(currentTime)
this.updateProgress(this.currentTime,this.duration)
}
这个地⽅同样的this.currentTime是当前时间(秒),this.curTime是格式之后的分秒格式
下⼀步我们就要更新进度条了,得到 当前时间和总时间 的⽐值 来更新进度条的宽度和⼩圆点距离左边的距离
updateProgress(currentTime, duration){// 更新进度条
this.precent =`${((currentTime / duration)*100).toFixed(5)}%`
},
<div class="progress"@click="clickProgress($event)"ref="progress">
<div class="line":></div>
<div class="dot":@touchstart='dotStart'@touchmove='dotMove'@touchend='dotEnd'></div>
</div>
3.3进度条点击播放拖拽播放
在 clickProgress⽅法⾥这样写
clickProgress(event){// 点击进度条时更新⾳频时间和进度条
const e = event || window.event
const position = e.clientX - e.currentTarget.offsetLeft // 当前点击的位置
const progressWidth =this.$refs.progress.offsetWidth // 进度条总宽度
this.$refs.audio.currentTime =((position / progressWidth)*this.duration)// 设置当前⾳频的播放时间
this.updateProgress(((position / progressWidth)*this.duration),this.duration)
}
这样就实现了点击进度条播放。
下⾯是拖拽功能的实现,使⽤原⽣的touchstart touchmove touchend来监听。
在touchmove时,获取⼩圆点拖动到距离进度条左边的距离,并实施更新进度条
// 移动的距离
let moveX = e.touches[0].pageX -83// 83是进度条距离浏览器的距离
// 进度条的宽度
const progressWidth =this.$refs.progress.offsetWidth
if(moveX >= progressWidth) moveX = progressWidth // 边界值判断
this.$refs.audio.currentTime =((moveX / progressWidth)*this.duration)// 实时更新播放时间this.updateProgress(((moveX / progressWidth)*this.duration),this.duration)// 更新进度条
}
在touchend时播放歌曲
touchEnd(e){
this.playSong()//调⽤播放歌曲⽅法
this.isPlaying =true
},
4.评论区的展⽰
⽐较简单 直接遍历得到的数据然后渲染就⾏。只是在切换歌曲时要把评论区给隐藏掉完整代码
HTML
<div >
<div class="blur-container":>
</div>
<div class="play-container">
<goBack :showGoBack='showGoBack'/>
<div class="cd"v-show="show"@click="show = !show"ref="cd">
<img :src="playingSong.blurPicUrl"width="60%">
</div>
<div class="lyrics"v-show="!show"@click="show = !show">
<div class="volume">
<i class="fa fa-volume-up"v-show="!isMuted"@click.stop.prevent="muted(true)"></i>
<i class="fa fa-volume-off"v-show="isMuted"@click.stop.prevent="muted(false)"></i>
<div class="volumeRange"><input type="range"min="0"max="100"v-model="volume"step="1"@input="handleVolumeChange"></div> </div>
<div class="lyrics-container">
<ul ref="lyricUL">
<li v-for="(item, i) in lyricsObjArr"::key="item.uid":data-index='i'ref="lyric">{{item.lyric}}</li> </ul>
html播放音乐代码</div>
</div>
<!-- 下⽅控件 -->
<div class="bottom">
<div class="bottom-line1">
<div class="like"@click="toggleLikeMusic"v-show="!like"><i class="fa fa-heart-o"></i></div>
<div class="like like-yes"@click="toggleLikeMusic(false)"v-show="like"><i class="fa fa-heart"></i></div>
<div class="download"@click="download"><i class="fa fa-download"></i></div>
<div class="comment"@click="showComment"><i class="fa fa-commenting-o"></i></div>
</div>
<div class="bottom-progress">
<div class="curTime">{{curTime}}</div>
<div class="progress"@click="clickProgress($event)"ref="progress">
<div class="line":></div>
<div class="dot":@touchstart='dotStart'@touchmove='dotMove'@touchend='dotEnd'></div>
</div>
<div class="allTime">{{allTime}}</div>
</div>
<div class="bottom-controls">
<div class="prev"@click="prevSong"><i class="fa fa-step-backward"></i></div>
<div class="pause"v-show="isPlaying"@click="pauseSong"><i class="fa fa-pause"></i></div>
<div class="play"v-show="!isPlaying"@click="playSong"><i class="fa fa-play"></i></div>
<div class="next"@click="nextSong"><i class="fa fa-step-forward"></i></div>
</div>
</div>
<!-- autio标签 -->
<audio @timeupdate="updateTime"@canplay="getDuration"@ended="ended":src="musicUrl"id="audio"ref="audio"></audio>
<comment :showCommentPanel='showCommentPanel'@getMoreComment='getMoreComment'@likeComment='toggleLikeComment'/>
</div>
</div>
</template>
CSS
<style scoped lang="scss">
.
blur-container{
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
position: relative;
z-index: 1;
filter:blur(50px);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论