·悄然 - 2024-12-17 15:19
·悄然 - 2024-12-15 15:12
·悄然 - 2024-12-9 12:32
·飞飞 - 2024-12-9 12:31
·小希 - 2024-12-7 11:50
·飞飞 - 2024-12-5 15:53
·飞飞 - 2024-12-3 16:42
·悄然 - 2024-12-3 16:41
·飞飞 - 2024-12-1 18:27
保姆级range进度条音频播放器开发教程(三)
在 保姆级range进度条音频播放器开发教程(二) 一讲中,我们去掉了 audio 控件的UI界面、用图片充当按钮接管音频播放/暂停的工作。不过,细心的朋友可能已经发现了一些问题,比如音乐播放结束之后按钮的旋转还在继续,抑或当设置了audio自动播放,音乐播放后按钮不会旋转,等等。这是因为缺乏相应的智能联动控制机制所致——我们只是通过按钮的点击事件设置了 --state 这个CSS变量来操控按钮。本节将重点处理这个问题,建立音频和按钮的完好关系,达到音频与按钮旋转动作的智能联动效果。这需要用到 audio 控件的两个事件:
① onpause : 暂停事件 用 JS 的 监听方法时,按规范,所有 onxxx 的元素事件,统统不要 on 前缀。例: aud.addEventListener('pause', () => {/*做点什么*/}); 注意:这里的 onpause 在 addEventListener() 中写成 pause,但它和 pause() 方法不是同一个东东,要区分开来:前者是元素的事件,与元素的点击事件同属一个类型,后者是audio对象的属性方法,用于发起一个暂停动作。 ② onplaying : 正在播放事件 同样地,JS监听事件的方法也不要前缀 on,例: aud.addEventListener('playing', () => {/*做点什么*/}); 【注意】audio 还有一个 onplay 事件,和 onplaying 不同,它表示音频(部分或全部)准备就绪可以播放了。onplaying 和 onplay 的主要区别不难理解,记住也不难(~ing后缀表示正在进行)。我们用前者 onplaying 而不是后者就在于它们的本质区别:我们要的结果是,音频是否已经在播放中。
假设我们已经有了一个处理按钮是旋转还是静止状态的函数 mState() ——我们稍后要编写它——,那么,可以想象,我们通过监听上述两个事件来运行这个函数,按钮的旋转与否就可以达到我们前述的所谓智能联动预期。理由:onpause 事件发生时,音乐暂停,mState 函数则会令 --state 这个CSS变量值变为 'paused'(又一个 paused!它是CSS的,不是audio的);onplaying 事件发生时,音乐正在播放中,则 mState 函数会令 --state 变量值变为 'running'(谢天谢地!CSS这回没有使用 playing)。这个可以理解吧?如果能理解,那就看看监听事件代码,否则需要花点时间慢慢琢磨,领会后再往下看:
aud.addEventListener('pause', () => mState()); aud.addEventListener('playing', () => mState());
代码非常简单,就是监听 pause(onpause) 和 playing(onplaying)事件,当这两个事件发生时,都运行 mState() 函数。下来就是重头戏:编写我们冰雪聪明的 mState() 函数,mState 是我们自己命名的,可以用其它的,我们之所以用 mState,m指music,state指状态,多少有点意思:
var mState = () => { if (aud.paused) { /* 如果audio处在暂停状态 */ btnplay.style.setProperty('--state', 'paused'); /* 让按钮的旋转停下 */ } else {/* 否则 */ btnplay.style.setProperty('--state', 'running'); /* 让按钮的转起来 */ } }; /* 用三目运算改写上述 mState 函数,感受一下语法糖的精美 */ var mState = () => btnplay.style.setProperty('--state', aud.paused ? 'paused' : 'running');
这个其实就是上一节图片按钮的功能之一,是从那里剥离出来的功能模块,不同的是现在这个功能用于函数而非元素的相关事件,它可以被反复调用——如前已述,两个 audio 控件监听事件时刻监听着这个函数,随时控制着按钮的旋转动作。 如果(if)条件语句的依据依然是 aud.paused,paused 对象属性是 audio 控件一个重要属性,上节提到过,它返回音频是否处于暂停状态,在对 audio 控件不使用异步编程的情况下,paused 属性是判断音频控件最为可靠的依据。
mState() 函数主要负责管理按钮的旋转状态(将来功能可以扩展),它的加持通过 audio 的 onpause 和 onplaying 两个监听事件对它的调用加以实现,从而介入对按钮运行状态的实质性管理。这样,按钮的点击事件就不用管自身旋转与否的问题,只需专心负责音乐的播放与暂停就好(我们用三目运算写法替代原来冗长的if语句):
btnplay.onclick = () => aud.paused ? aud.play() : aud.pause();
解释一下三目运算,也称三元运算。上句是经典的三目运算语句,问号 ? 问,前面的 aud.paused 是否成立?答,成立的话,播放音乐【aud.play();】。冒号 : 说,否则,停止音乐【aud.pause();】。
最后,组织一下新的代码,看看我们的产品是不是有些长进:
<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=4046323"></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 mState = () => btnplay.style.setProperty('--state', aud.paused ? 'paused' : 'running'); aud.addEventListener('timeupdate', () => { mprog.value = aud.currentTime / aud.duration * mprog.max; }); aud.addEventListener('pause', () => mState()); aud.addEventListener('playing', () => mState()); btnplay.onclick = () => aud.paused ? aud.play() : aud.pause(); </script>
运行上述代码,音乐播放完毕,按钮会停止旋转。给 audio 标签加入 autoplay,如果浏览器支持自动播放,按钮会自动旋转,反之如果浏览器不支持自动播放,按钮静止不动、直至我们去点击它。pencile code 可以运行上述代码,也可以将代码存为本地html文件再运行。
评论列表 [2条]
#2 | 了了 于 2024-1-30 17:48 发布: autoplay加上后,图标和进度条可自动运行。。三目运算写法好象贴子里经常看到。
#1 | 飞飞 于 2024-1-28 10:25 发布: 这个播放器教程就是天下第一的好教程。。:))