1.首先:要实现,当前歌曲播放到的时间和总的歌曲时间,以及进度条跟着时间变化
思路:通过audio.duration获取总的歌曲时间,然后监听歌曲的timeupdate获取当前的播放时间audio.currentTime,最后通过audio.currentTime/audio.duration的得到的百分比值设置为滚动条高亮的宽度,另外audio.duration需要监听canplay才能得到准确的值,然后在歌曲播放结束后监听ended事件,将当前播放时间和高亮进度条都还原
<audio src="#"></audio>
<div class="progress-wrapper">
<div class="current-time">00:00</div>
<div class="progress-bottom">
<span class="progress-dot"></span>
<div class="progress-top"></div>
</div>
<div class="songs-time">04:00</div>
</div>
.progress-wrapper{
padding: 14px;
display: flex;
align-items: center;
}
.current-time,.songs-time{
color: #fff;
}
.current-time{
margin-right: 10px;
}
.songs-time{
margin-left: 10px;
}
.progress-bottom{
flex: 1;
height: 0.4vh;
background: rgba(255, 255, 255, 0.8);
position: relative;
}
.progress-top{
height: 100%;
position: absolute;
left: 0;
top: 0;
background: #D43B32;
transition: all .3s linear;
}
.progress-dot{
width: 1vw;
height: 16px;
width: 16px;
border-radius: 50%;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
background: #fff;
}
let view = {
audioListener(song){
//重新渲染的时候如果audio里的src是#就让它等于当前的song.url否则,就不去重新渲染
if(this.$el.find('audio').attr('src') !== song.url){
this.audio = this.$el.find('audio').attr('src',song.url)
this.audio.on('canplay',()=>{
this.getSongLength()
})
this.audio.on('ended',()=>{
window.eventHub.emit('songEnd')
})
this.audio.on('timeupdate',()=>{
this.updateProgress()
this.lyricProgress(this.audio[0].currentTime)
})
}
},
getSongLength(){
this.time = this.audio[0].duration
this.timeFormat()
this.$el.find('.songs-time').text(this.time)
},
timeFormat(){
let minuter = parseInt(this.time / 60)
let second = Math.floor(this.time % 60)
minuter = (minuter < 10) ? ('0' + minuter) : minuter
second = (second < 10) ? ('0' + second) : second
this.time = `${minuter}:${second}`
},
getCurrentTime(){
this.time = this.audio[0].currentTime
this.timeFormat()
this.$el.find('.current-time').text(this.time)
},
updateProgress(){
this.value = this.audio[0].currentTime / this.audio[0].duration
this.$el.find('.progress-top').css('width',`${this.value * 100}%`)
this.$el.find('.progress-dot').css('left',`${this.value * 100}%`)
this.getCurrentTime()
},
audioEnd(){
this.$el.find('.progress-top').css('width',0)
this.$el.find('.progress-dot').css('left',0)
this.$el.find('.current-time').text('00:00')
},
}
let controller = {
init(view,model){
this.view = view
this.model = model
thsi.view.audioListener()
},
bindEventHub(){
window.eventHub.on('songEnd',()=>{
this.model.data.status = 'pause'
this.view.render(this.model.data)
this.view.lyricMove(24)
this.view.audioEnd()
})
}
}
2.点击某一位置让当前播放时间跳到那个位置
思路:通过监听最外层的总的进度条的mousedown事件,通过e.offsetX获取点击位置距离进度条开始的位置的距离,然后载获取进度条的总长度,通过当前距离/进度条总长度然后再乘以当前歌曲的总时长(duration)就能得到当前位置的时长让后把它赋值给audio.currentTime即可
this.view.$el.on('mousedown','.progress-bottom',(e)=>{
this.current = $(e.currentTarget)
let left = e.offsetX
let motallength = this.current.width()
let audio = this.view.$el.find('audio')[0]
// 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
if (!audio.paused || audio.currentTime != 0) {
audio.currentTime = audio.duration * (left/motallength)
}
})
3.拖动当前滑块到对应位置,歌曲播放到对应位置
实现思路:通过mosedown/mousemove/mouseup来监听电脑端的拖动,通过touchstart/touchmove/touchend来监听手机端的拖动,只要写三个方法,然后在方法里判断touch是否存在,之后也是获取到当前拖动到的位置的长度/总的进度条*歌曲时间duration就可以
preventDefaultEvent(){
// 禁止默认事件(避免鼠标拖拽进度点的时候选中文字)
if (this.event && this.event.preventDefault) {
this.event.preventDefault();
} else {
this.event.returnValue = false;
}
// 禁止事件冒泡
if (this.event && this.event.stopPropagation) {
this.event.stopPropagation();
} else {
window.event.cancelBubble = true;
}
},
down(e){
this.flag = true
this.event = e || window.event
this.clientX = this.event.touches ? this.event.touches[0].clientX : this.event.clientX
this.dot = this.view.$el.find('.progress-dot')[0]
this.progress = this.view.$el.find('.progress-bottom')[0]
this.left = this.clientX - this.dot.offsetLeft
this.preventDefaultEvent()
},
moveLength(){
this.maxRightLength = this.progress.offsetWidth
if(this.left1 < 0){
this.left1 = 0
}else if(this.left1 > this.maxRightLength){
this.left1 = this.maxRightLength
}
},
move(e){
this.event = e || window.event
if(this.flag){
this.clientX = this.event.touches ? this.event.touches[0].clientX : this.event.clientX
this.left1 = this.clientX - this.left
this.moveLength()
this.motalLeft = this.left1/this.progress.offsetWidth
let audio = this.view.$el.find('audio')[0]
audio.currentTime = this.motalLeft *audio.duration
}
},
end(){
this.flag = false
},
bindEvent(){
this.view.$el.on('mousedown','.progress-dot',this.down.bind(this))
this.view.$el.on('touchstart','.progress-dot',this.down.bind(this))
this.$document.on('mousemove','.progress-dot',this.move.bind(this))
this.$document.on('touchmove','.progress-dot',this.move.bind(this))
this.$document.on('mouseup','.progress-dot',this.end.bind(this))
this.$document.on('touchend','.progress-dot',this.end.bind(this))
}
网友评论