赞
踩
由于课程要求,不使用任何框架(诸如jquery之类的)来实现一个音乐播放器,我查找了半天没能找到自己心仪的,索性便自己写了。写好之后发出来分享一下。
话不多说,首先放图。
播放列表做的属实难看了点,但是我想不到什么优化的好点子,又嫌麻烦不想给他加上编曲人之类的信息,索性就这样放着了。如果有什么优化的点子可以私信一起探讨一下。
页面布局灵感来自于qq音乐。
进度条功能
时间功能
播放/暂停功能
上一首/下一首
切换播放模式功能
音量调节功能
播放MV功能
倍速功能
音乐列表功能
进度条会随着音乐的播放逐渐向后移动,这是通过audio的timeupdate事件来实现的,每时每刻都会重新计算进度条长度。
- // 更新进度条
- audio.addEventListener('timeupdate', updateProgress); // 监听音频播放时间并更新进度条
- function updateProgress() {
- var value = audio.currentTime / audio.duration;
- progress.style.width = value * 100 + '%';
- playedTime.innerText = transTime(audio.currentTime);
- }
点击进度条可以跳转至指定地方播放,这是通过所有DOM元素都有的事件mousedown来实现的。
- // 点击进度条跳到指定点播放
- progressTotal.addEventListener('mousedown', function (event) {
- // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
- if (!audio.paused || audio.currentTime != 0) {
- var pgsWidth = parseFloat(window.getComputedStyle(progressTotal, null).width.replace('px', ''));
- var rate = event.offsetX / pgsWidth;
- audio.currentTime = audio.duration * rate;
- updateProgress(audio);
- }
- });
更新进度条的同时左下角时间会更新,这是通过这一行代码来实现的:
playedTime.innerText = transTime(audio.currentTime);
这个功能实现起来很简单,检测当前音频播放状态并作出相应反应即可。
- // 暂停/播放功能实现
- pause.onclick = function (e) {
- if (audio.paused) {
- audio.play();
- rotateRecord();
- pause.classList.remove('icon-play');
- pause.classList.add('icon-pause');
- } else {
- audio.pause();
- rotateRecordStop();
- pause.classList.remove('icon-pause');
- pause.classList.add('icon-play');
- }
- }
对相应按钮添加点击事件,点击上一首按钮时改变当前播放音乐的序号,并且重新载入该音乐。下一首功能也是如此实现。
- // 上一首
- skipForward.addEventListener('click', function (event) {
- musicId = musicId - 1;
- if (musicId < 0) {
- musicId = 3;
- }
- initAndPlay();
- });
-
- // 下一首
- skipBackward.addEventListener('click', function (event) {
- musicId = musicId + 1;
- if (musicId > 3) {
- musicId = 0;
- }
- initAndPlay();
- });
有三种内置的播放模式:单曲循环,随机播放,列表循环。每次点击播放模式按钮后切换至下一种播放模式。
- // 播放模式设置
- var modeId = 1;
- mode.addEventListener('click', function (event) {
- modeId = modeId + 1;
- if (modeId > 3) {
- modeId = 1;
- }
- mode.style.backgroundImage = "url('img/mode" + modeId.toString() + ".png')";
- });
-
- audio.onended = function () {
- if (modeId == 2) {
- // 跳转至下一首歌
- musicId = (musicId + 1) % 4;
- }
- else if (modeId == 3) {
- // 随机生成下一首歌的序号
- var oldId = musicId;
- while (true) {
- musicId = Math.floor(Math.random() * 3) + 0;
- if (musicId != oldId) { break; }
- }
- }
- initAndPlay();
- }
实时获取滑块当前的长度并且更新音频音量,用到的还是audio的timeupdate函数。同时点击音量调节按钮之后可以设置静音,使用click事件即可实现。
- // 滑块调节音量
- audio.addEventListener('timeupdate', updateVolumn);
- function updateVolumn() {
- audio.volume = volumeTogger.value / 70;
- }
-
- // 点击音量调节设置静音
- volume.addEventListener('click', setNoVolumn);
- function setNoVolumn() {
- if (volumeTogger.value == 0) {
- if (lastVolumn == 0) {
- lastVolumn = 70;
- }
- volumeTogger.value = lastVolumn;
- volume.style.backgroundImage = "url('img/音量.png')";
- }
- else {
- lastVolumn = volumeTogger.value;
- volumeTogger.value = 0;
- volume.style.backgroundImage = "url('img/静音.png')";
- }
- }
此处我考虑了要将MV放置在新窗口还是旧的窗口,最终还是决定新开一个窗口来播放MV。那么这就涉及到窗口之间的传值。使用window.sessionStorage来实现。
- // MV功能
- MV.addEventListener('click', function (event) {
- // 向新窗口传值
- var storage_list = window.sessionStorage;
- storage_list['musicId'] = musicId;
- window.open("video.html");
- });
此处放上新窗口的body部分代码:
- <body>
- <video controls width="250">
- <source id="source" src="mp4/video0.mp4" type="video/mp4">
- </video>
- </video>
- <script>
- //获取前面的存储的musicId值
- var storage = window.sessionStorage;
- var cur_str = storage.musicId;
- document.getElementById('source').src = "mp4/video" + cur_str.toString() + ".mp4";
- </script>
- </body>
由于该部分代码量很小,并且不是项目主体部分,因此css和javascript均使用内嵌式来实现。
最终效果:点击不同音乐的MV按钮,可以打开相应的MV视频界面。
一共内置了四种倍速:1.0X,1.5X,2.0X,0.5X。每次点击按钮后会切换到下一种倍速,并改变其UI。由于此处的倍速种类较少,直接使用if else来实现这一功能。如果倍速种类较多,则需要使用int 变量与string变量之间的相互转化来实现。
- // 倍速功能(这里直接暴力解决了)
- speed.addEventListener('click', function (event) {
- var speedText = speed.innerText;
- if (speedText == "1.0X") {
- speed.innerText = "1.5X";
- audio.playbackRate = 1.5;
- }
- else if (speedText == "1.5X") {
- speed.innerText = "2.0X";
- audio.playbackRate = 2.0;
- }
- else if (speedText == "2.0X") {
- speed.innerText = "0.5X";
- audio.playbackRate = 0.5;
- }
- else if (speedText == "0.5X") {
- speed.innerText = "1.0X";
- audio.playbackRate = 1.0;
- }
- });
首先需要在界面右方固定音乐列表面板:
- <div class="music-list" id="music-list">
- <div class="music-list-container">
- <div class="music-list-title">播放队列</div>
- <hr class="line">
- <div class="all-list">
- <div id="music0">洛春赋</div>
- <div id="music1">Yesterday</div>
- <div id="music2">江南烟雨色</div>
- <div id="music3">Vision pt.II</div>
- </div>
- </div>
- </div>
实现的效果如下图:
效果实在不算好看,但我也没想到什么能够让他变得美观的优化方法。
对其加上css滑动动画:
- @keyframes hideAni {
- from {
- transform: translateX(0%);
- }
-
- to {
- transform: translateX(100%);
- }
- }
-
- @keyframes showAni {
- from {
- transform: translateX(100%);
- }
-
- to {
- transform: translateX(0%);
- }
- }
最后在js中加入打开面板和关闭面板的逻辑,实现起来很简单,使用click事件即可。
- // 点击列表展开音乐列表
- list.addEventListener('click', function (event) {
- musicList.classList.remove("list-card-hide");
- musicList.classList.add("list-card-show");
- musicList.style.display = "flex";
- closeList.style.display = "flex";
- closeList.addEventListener('click', closeListBoard);
- });
-
- // 点击关闭面板关闭音乐列表
- function closeListBoard() {
- musicList.classList.remove("list-card-show");
- musicList.classList.add("list-card-hide");
- closeList.style.display = "none";
- }
打开列表面板时,左侧实际上覆盖了一个透明的面板,由此来实现点击空白部分关闭面板的功能。需要注意的是关闭面板后需要将该透明面板的display设置为none,否则会遮蔽下层按钮的点击事件。
代码中使用到的包括图片、视频、音频等所有素材仅为展示使用,相互之间没有任何关联,如有需要可自行更改。
github地址:GitHub - falysha/musicPlayer: 原生HTML+CSS+JS,未使用任何框架
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。