问题描述:做一个音乐播放器的UI,想要使用slider做歌曲进度条,能拖动那种。为了使进度条自动向前,设置了一个interval,每500ms更新一次,用audioctx.currentTime更新,有拖动的时候用拖动值更新。拖动进度条的时候发现:从B点拖到A点,小圆圈回先退回B点,然后弹回A点。声音播放没有回退现象,就是进度条piaji一下看得不爽。
解决方案:经过一系列尝试,最后在三个地方log:seek后的currentTime,拖动值,以及用来更新的currentTime:
slider(e:any){ let value=Number(e.detail.value); audioctx.seek(value); console.log("0:"+audioctx.currentTime);this.setData({ isChanging:false, timeId:setInterval(()=>{ if(this.data.isPlaying&&!this.data.isChanging){ this.update(); } },500) }) }, update(newVal?:Number){ let value=newVal?newVal:audioctx.currentTime; console.log("1:"+value); console.log("2:"+audioctx.currentTime); let max=audioctx.duration; ...... },
log结果如下:
可以发现是seek后currentTime并没有立即更新导致的回退。但不知道为什么setTimeout并没有用,于是只能自己算时间了,拖动时清除上一个interval,拖动结束重新定时,反正误差不大:
slider(e:any){ let value=Number(e.detail.value); audioctx.seek(value); console.log("0:"+audioctx.currentTime); let i=0; this.setData({ isChanging:false, timeId:setInterval(()=>{ if(this.data.isPlaying&&!this.data.isChanging){ this.update(value+0.5*i); i++; } },500) }) }, update(newVal?:Number){ let value=newVal?newVal:audioctx.currentTime; console.log("1:"+value); console.log("2:"+audioctx.currentTime); let max=audioctx.duration; while(value>lyricTime[lyricIndex]&&value>lyricTime[lyricIndex+1]){ lyricIndex++; if(lyricIndex===lyricTime.length) break; } while(value<lyricTime[lyricIndex]&&value<lyricTime[lyricIndex-1]){ lyricIndex--; if(lyricIndex===0) break; } this.setData({ max:max, value:value, currentTop:lyricPos[lyricIndex]-lyricPos[0], currentIndex:lyricIndex }); },