当前位置: 首页 > Web前端 > HTML5

实现一个歌曲播放暂停淡入淡出效果——Electron+Vue写一个播放器(一)

时间:2023-04-05 22:56:37 HTML5

前言我决定开始写博客了,先从简单的东西说起吧。今天还在琢磨各个平台音乐的实现细节,发现他们在播放和暂停歌曲的时候,都会有一个短暂的淡入淡出效果。下面我们来实现一下。目前设计思路比较好的方法是在收到用户的播放请求时,通过短时间内不断降低音量直到为0来调用audio元素的暂停接口,收到时先调用audio元素用户暂停请求元素的播放界面,并在短时间内将音量增加到用户设置的音量。想到某个步骤需要连续执行,脑子里冒出两个方法,setTimeOut或者setInterVal和requestAnimationFrame,因为没有耗时的连续异步操作,所以不需要用setTimeOut来避免累积效应setInterVal(如果你真的有这些操作,你应该避免在主线程上执行它们)。我们希望音频的淡入淡出能够足够平滑,不要因为音量变化间隔过大而产生颗粒感的声音,虽然使用setInterVal时回调执行间隔不是固定的,只是当执行栈为空时轮到异步队列的任务执行,但是目前没有任务会阻碍回调函数的执行,而requestAnimationFrame允许在屏幕刷新时调用回调函数,这样音量变化的频率就变得固定了,看起来也顺滑了一点(用在非动画的渲染任务上真的合适吗?)。纸上谈兵很容易理解,所以我决定两者都实现,比较一下效果。首先我们来看看淡入淡出和不淡入淡出的区别。单击此处查看示例。下面给出requestAnimationFrame下的实现。datadata(){return{...volume:1,//用户设置的歌曲音量fadeVolume:0,//歌曲当前音量,区别于volume,这个变量是记录songwhenitfadein淡出时的实时音量volumeFadeInFlag:null,//保存歌曲淡入的定时器volumeFadeOutFlag:null,//保存歌曲淡出的定时器...}}然后增加或循环递减fadeVolume的值,直到音量为0,例如淡出代码为songVolumeFadeOut(audio){this.volumeFadeInFlag&&cancelAnimationFrame(this.volumeFadeInFlag)const_this=this;(functionfadeOut(){if(_this.fadeVolume-0.02<=0){_this.fadeVolume=0audio.volume=_this.fadeVolumecancelAnimationFrame(_this.volumeFadeOutFlag)_this.volumeFadeOutFlag=nullaudio.pause()}else{_this.fadeVolume=_this.fadeVolume-0.02_this.fadeVolume=Number(_this.fadeVolume.toFixed(2))audio.volume=_this.fadeVolume_this.volumeFadeOutFlag=requestAnimationFrame(fadeOut)}})()}注意在执行淡出循环之前需要清除淡入循环。如果不这样做,如果用户突然点击暂停和播放按钮,会同时出现多个淡入和淡出。而且都达不到终止条件,所以陷入死循环,因为刷新率大概是每秒60次,增量设置为0.02,可以在里面完成淡入淡出大约一秒钟。写完淡出和淡入的代码后,为了找到执行时间,我把淡入放在了audio元素的play事件的回调函数中,所以淡入的代码不需要手动调用声音的。收到音频暂停请求时执行淡出。onPlay(){...//当窗口最小化或隐藏时,requestAnimationFrame会被推迟到窗口恢复时,这不是我们想要的if(document.visibilityState=='visible'){this.songVolumeFadeIn(audio)}else{//因此当窗口不可见时我们使用setInterval而不是requestAnimationFramethis.songVolumeFadeInByInterval(audio)}...}...watch:{playing(){...if(document.visibilityState=='visible'){this.songVolumeFadeOut(audio)}else{this.songVolumeFadeOutByInterval(audio)}...}}如前所述,requestAnimationFrame是为动画设计的API,目的是提高性能和电池寿命,因此在大多数浏览器中,当requestAnimationFrame()在后台选项卡或隐藏的