保姆级range进度条音频播放器开发教程(四)

位置: 首页 > 前端三套件
[发布: 2024.1.29  作者: 马黑  阅读: 118]

到第三节 保姆级range进度条音频播放器开发教程(三) 的时候,我们的range进度条播放器不仅有模有样,还与音乐的播放/暂停智能联动,算是成功的作品了。下一步,我们想让 range 滑杆发挥更大的作用,即可以通过拖曳滑杆的滑块改变音频的播放位置,而不仅仅是显示音乐的播放进度。这将是本节的核心内容。

range滑块自身是可以随意拖动的,不过,它现在由 audio 的 timeupdate 监听事件控制着,在音乐播放的时候,拖曳滑块并不管用,timeupdate 监听事件总是会将其复位到音频的当前播放位置。我们得设计一个机制,以实现如下功能:当用户想要改变播放位置时,我们让 timeupdate 监听事件暂停工作,把滑杆滑块的滑动权交出来,待用户改变音乐的播放位置操作结束了再将滑动权还给它。

这需要引入一个布尔变量,我们用 mseek 来命名,m 还是music,seek 本意查找,这里指用户查找新的播放位置(mseek只是一个命名,可以随意)。当 mseek 为真(true),表明用户要进行进度调节操作,timeupdate 监听事件就先不驱动 range 的运行,待用户操作完毕,即当 mseek 为假(false)之时,timeupdate 监听机制继续工作。看看怎么声明 mseek 变量:

var mseek = false;

var 是 JS 声明变量的关键词,除它以外,还有 let,const,它们的区别先不用理睬,我们就用 var 好了。var 之后紧接着一个自定义变量名称(彼此间有空格),然后用等号给它一个值,布尔变量非真即假,真表示为 true,假表示为 false,我们上面给 mseek 的赋值是 false,这又为什么呢?因为,开始的时候,用户没有去操作进度调整,这时呢,timeupdate 监听机制要驱动 range 的进度运行。对应地,audio 的 timeupdate 监听事件我们要给它添加一个条件语句:

var mseek = false;

aud.addEventListener('timeupdate', () => {
	if (!mseek) mprog.value = aud.currentTime / aud.duration * mprog.max;
});

注意红色代码,它就是条件语句,if (!mseek) 相当于 if (mseek !== true)、等同于 if (mseek === false) ,就是如果 mseek 变量不为真之意,具体来说是,如果用户没有手动调节进度之时。感叹号 ! 在这里表示 mseek 的否定,三个等号表示绝对等于,感叹号加两个等号表示绝对不等于,这都太复杂,所以我们用 !mseek 来表示不为真即不等于真。if (!mseek) 语句加持后,timeupdate监听事件就更加聪明了,它指挥进度条的权限完全依赖于 mseek 变量值的变化:为假时驱动进度条的运行,为真时是用户正在手动调节进度,就不瞎掺和来着。这样,我们下一步要做的就是,如何获知用户正在调节进度了。

用户调节播放进度,需要在 range 滑块上按下鼠标左键,JS对此有个对应的处理事件,叫 onmousedown,意思是鼠标左键按下之时,可用于任意可视元素。页面上鼠标按下的动作频繁,我们只需针对 input 的 range 控件,它的 id 为 mprog,在它上面按下鼠标左键时:

mprog.onmousedown = () => mseek = true;

意思是,mprog 元素之上,当鼠标左键按下时,执行 mseek = true 语句,就是,令 mseek 布尔变量值为真。mseek 为真,timeupdate 监听事件就不再驱动 mprog 的运行,用户就可以随意拖动滑杆上的滑块了。

用户调节完毕,mseek 的值还需要变回假,以便进度条能够显示当前正确的播放位置。这得用到JS的鼠标松开事件,onmouseup,同样地,我们只管 mprog 的鼠标松开事件:

mprog.onmouseup = () => mseek = false;

鼠标键松开时就是需要改变音乐播放位置的时候,这又用到 input type="range" 元素即滑杆的 onchange 或 oninput 事件,这两个事件都表示滑杆 value 值改变之时,我们选用 onchange 事件(其实用哪个都行),它在鼠标左键或键盘方向键松开之时触发,代码如下:

mprog.onchange = () => /* 做点什么 */;

“做点什么”又是一个要处理的一个问题,这只是数学问题,它还是 aud.duration、aud.currentTime、mprog.vallue、mprog.max 即音频控件总时长、当前播放时间和滑杆当前值、总值之间的数学对应关系问题,列式与求 aud.currentTime(当前播放时间位置)值演示如下:

aud.duration / aud.currentTime = mprog.vallue / mprog.max →
aud.currentTime = mprog.value / mprog.max * aud.duration

这样,我们可以写出音频控件的 onchange 事件代码了:

mprog.onchange = () => aud.currentTime = aud.currentTime = mprog.value / mprog.max * add.duration;

至此,可以整合一~四节的代码了,下面的代码已将css代码进行了压缩,同时audio控件加入了自动播放、循环播放属性:

<style>
#mplayer { position: absolute; text-align: center; color: white; }
#mplayer p { margin: 0; padding: 0; }
#mprog { width: 240px; accent-color: darkgreen; outline: none; cursor: pointer; }
#btnplay { width: 80px; height: 80px; cursor: pointer; animation: rotating 6s infinite linear var(--state); }
@keyframes rotating { to { transform: rotate(360deg); } }
</style>

<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2113720220" autoplay loop></audio>
<div id="mplayer">
	<p><img id="btnplay" src="https://638183.freep.cn/638183/small/002_133507167677724892.png" title="播放/暂停" alt="" /></p>
	<p><input id="mprog" type="range" min="0" max="100" step="0.1" value="0" title="调节进度" /></p>
</div>

<script>

var mseek = false;

var mState = () => btnplay.style.setProperty('--state', aud.paused ? 'paused' : 'running');

aud.addEventListener('timeupdate', () => {
	if (!mseek) mprog.value = aud.currentTime / aud.duration * mprog.max;
});
aud.addEventListener('pause', () => mState());
aud.addEventListener('playing', () => mState());

mprog.onmousedown = () => mseek = true;
mprog.onmouseup = () => mseek = false;
mprog.onchange = () => aud.currentTime = aud.currentTime = mprog.value / mprog.max * aud.duration;

btnplay.onclick = () => aud.paused ? aud.play() : aud.pause();

</script>

上述代码已经实现了手工调整音频播放进度的功能,不论音乐在播放中还是在暂停中,我们的range进度条播放器更接近完美了。可以在 pencil code 运行上述代码或将代码存为本地html文档后运行。啰嗦一下,调节播放进度存在两种情形:音乐播放时和音乐暂停时,大家可以体验一下。

前一篇: 保姆级range进度条音频播放器开发教程(三)
下一篇: 保姆级range进度条音频播放器开发教程(五)

发表评论:

  
 

评论列表 [2条]

#2 | 飞飞 于 2024-1-30 20:35 发布: aud.currentTime = mprog.value / mprog.max * aud.duration mprog.value = aud.currentTime / aud.duration * mprog.max 小白把这两句对比起来看,更清楚些。。。

#1 | 小希 于 2024-1-29 10:03 发布: 我们的range进度条播放器更接近完美了。。。。为完美干杯。。

Copyright © 2023 All Right Reserved 马黑PHP文章管理整站系统v1.8
联系我们: gxblk@163.com