今天接着完成部分音乐播放器的功能
主要完成以下功能:

  1. 默认播放第一首歌,点击播放键即可播放,点击暂停即可暂停
  2. 点击列表中任意歌曲即切换播放该歌曲
  3. 实现切换到上一首或下一首的功能
  4. 进度条随歌曲前进

这里我们用到ajax异步获取到json文件,所以一定要记得在终端启用http-server来在服务端查看,在本地查看不到。

一、默认设置

接上一篇文章【小河今学 | Html+CSS+JS+JQ】音乐播放器1-布局,接下来就是要用js实现音乐播放器的具体功能。
首先我们先设置默认歌曲,这里我选择第一首歌为默认播放的歌曲,即打开页面后第一首歌是默认被选中的。

// 获取到播放器audio
            var player = document.getElementById('player');
            // 设置初始值
            var index = 0; // 默认初始播放第一首歌
            // 默认第一首歌
            // 设置被选中样式
            $('.content li').eq(index).addClass('click');
            // 将json中的歌曲地址赋给audio
            player.src = songs[index].url;

这时候打开页面控制台,可以看到原本的audio标签已经赋了一个src,即第一首歌的src

html5音频 js控制 js控制音乐播放_进度条


接着我们要让他播放和暂停,就要用到audio的play()方法和pause()方法

// 点击播放按钮,播放音乐
            $('.pp').click(function(){
                // 如果是播放按钮
                if($(this).hasClass('play')){
                    player.play();
                    // 播放图标变成暂停图标
                    $(this).removeClass('play');
                    $(this).addClass('pause');
                }else{
                    player.pause();
                    // 暂停图标变成播放图标
                    $(this).removeClass('pause');
                    $(this).addClass('play');
                    // 暂停后清理计时器,不清理的话每一秒钟都在调用计时器里的方法
                    // 但是同时再次点击时有一秒钟的延迟问题,这里如果是为了页面美观可以不要清理计时器
                    clearInterval(timer);
                }
            })

设置完后,再次打开页面,这里点击播放键即可播放音乐,同时播放键图标改变。

html5音频 js控制 js控制音乐播放_html5音频 js控制_02

二、点击播放任意歌曲

在这里我一开始将播放歌曲的方法直接写在li标签的click方法里,但是后续在上一曲下一曲的切换中又用到了播放歌曲,所以这里我直接封装改方法

// 设置一个播放方法
            function play(index){
                // 改变audio的src
                player.src = songs[index].url;
                player.play();
                // 点击别的歌曲时,若当前播放键为播放(三角形),则换成暂停(直立等于)
                if($('.pp').hasClass('play')){
                    // console.log(11)
                    $('.pp').removeClass('play')
                    $('.pp').addClass('pause');
                }
            }

这里的index即传进来的li标签的下标。
在点击任意歌曲播放里,需要获取到当前点击的这个歌曲的下标

// 定义一个点击方法,当点击这首歌时播放这首歌
            $('.content li').click(function() {
            	// 获取到当前被点击的li标签的下标
                var newIndex = $(this).index();
                // console.log(newIndex);
                // 被点击的歌曲激活样式,其他的不被激活
                $(this).addClass('click').siblings().removeClass('click')
                // 调用播放方法
                play(newIndex);
            })

接着回到页面,点击任意歌曲都能开始播放,点击暂停就可停止。

三、实现切换到上一首或下一首的功能

和上面点击播放的功能类似,只是需要调整获得的数组下标。
首先切换到上一首里,我们需要注意当前选中的若是第一首,则再次点击切换到上一首要回到最后一首歌,因此具体代码如下:

$('.prev').click(function() {
                // 获取当前播放的歌下标减一
                var newIndex =  $('.click').index() - 1;
                
                // 如果获取的是第一首歌的下标0,减一为-1,作条件判断语句
                newIndex = newIndex < 0 ? $('.content li').length - 1 : newIndex;
                // console.log(newIndex)
                // 将click赋给获得的新下标的li标签
                $('.content li').eq(newIndex).addClass('click').siblings().removeClass('click');
                // 调用play方法
                play(newIndex)
            })

切换到下一首的道理同上

// 点击下一曲,进到下一曲(如果当前是最后一首,则回到第一首)
            $('.next').click(function() {
                // 获取当前播放的歌下标加一
                var newIndex =  $('.click').index() + 1;
                
                // 如果获取的是最后一首歌的下标4,加1为5,作条件判断语句
                newIndex = newIndex > 4 ? 0 : newIndex;
                // console.log(newIndex)
                // 将click赋给获得的新下标的li标签
                $('.content li').eq(newIndex).addClass('click').siblings().removeClass('click');
                // 调用play方法
                play(newIndex)
            })

四、实时时间变化

这里我们需要先搞定实时时间和总时间,即

html5音频 js控制 js控制音乐播放_进度条_03


获取到总时间,我们需要用到audio的duration属性。在这里我们可以先console.dir(player),看看它有哪些属性值。

html5音频 js控制 js控制音乐播放_前端_04


控制台输出后,找到duration,就是我们要的总时长。这里以秒为单位,我们需要将它修改成我们需要的格式,再渲染到前端页面上。由于总时长和实时时间的格式修改代码重复,因此这里我将它封装为一个方法。

// 定义一个修改时间格式的方法
            function fixTime(time){
                // 这里获得的总时长是秒数,我们要把它转换成时间格式
                var m = parseInt(parseInt(time) / 60);   // 得到分钟数
                var s = parseInt(parseInt(time) - m * 60);   // 得到秒数
                // console.log(s)
                // 拼接格式mm:ss
                var at = (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s);
                return at;
            }

这里使用paresInt()是为了得到整数。拼接完毕后记得return才能拿到我们要的字符串。
接着写总时长,这里我原本直接要获得player.duration,但控制台一直输出为NaN,搜索后发现是因为音源是异步加载,所以我们要等到它加载结束后才能获得它的总时长,因此这里我们要用到loadedmetadata

// 获取当前歌曲的总时长,注意这里加载音频资源是异步的,如果没有加载完成就获取歌曲总时长,则duration返回NaN
            player.addEventListener('loadedmetadata',function(){    //加载完成后
                at = fixTime(player.duration);
                // 把拼接好的时间渲染到前端
                $('.alltime').html(at);
            })

接着写实时时间,因为要实时渲染到前端,这里我们需要用到一个计时器,每秒钟渲染一次。为了避免全局污染,我们首先要在全局定义一个timer=null。

// 显示实时进度
            player.addEventListener('playing',function(){
                // 这里需要用到计数器,一秒钟刷一次,这样才能达到实时的效果
                timer = setInterval(() => {
                    ct = fixTime(player.currentTime);
                    $('.curtime').html(ct);
                }, 1000);
            })

写完后回到页面,可以看到实时时间开始前进,同时控制台每一秒钟刷新一次<span class="curtime"></span>,这时候按下暂停键可以看到控制台还在不停刷新,因此我们要回到点击暂停的地方,加上一个clearInterval(timer);来清除计时器。

// 点击播放按钮,播放音乐
            $('.pp').click(function(){
                // 如果是播放按钮
                if($(this).hasClass('play')){
                    player.play();
                    // 播放图标变成暂停图标
                    $(this).removeClass('play');
                    $(this).addClass('pause');
                }else{
                    player.pause();
                    // 暂停图标变成播放图标
                    $(this).removeClass('pause');
                    $(this).addClass('play');
                    // 暂停后清理计时器,不清理的话每一秒钟都在调用计时器里的方法
                    // 但是同时再次点击时有一秒钟的延迟问题,这里如果是为了页面美观可以不要清理计时器
                    clearInterval(timer);
                }
            })

最后当歌曲播放结束后,图标需要变回播放键,同时清除计时器。

// 当一首歌播放完毕后,改变图标,同时清理计时器
            player.addEventListener('ended',function () {
                $('.pp').removeClass('pause');
                $('.pp').addClass('play');
                clearInterval(timer);
            })

五、进度条前进

在原先的html里,除了progress还有一个p,这个p就是前进的进度条。我们要获取当前时间在总时间的占比,转换成进度条的百分比。

// 进度条跟着前进,首先获得当前进度长度
                    allTime = parseInt(player.duration);
                    curTime = parseInt(player.currentTime);
                    var proWidth = (curTime / allTime) * $('.progress').width();
                    $('.progress p').width(proWidth)

同时,播放完后我发现进度条没有全部铺满,因此进行一个判断语句。完整代码如下:

// 显示实时进度
            player.addEventListener('playing',function(){
                // 这里需要用到计数器,一秒钟刷一次,这样才能达到实时的效果
                timer = setInterval(() => {
                    ct = fixTime(player.currentTime);
                    $('.curtime').html(ct);
                    // 进度条跟着前进,首先获得当前进度长度
                    allTime = parseInt(player.duration);
                    curTime = parseInt(player.currentTime);
                    var proWidth = (curTime / allTime) * $('.progress').width();
                    $('.progress p').width(proWidth)
                    // console.log(proWidth)
                    // 测试后发现播放完后进度条没有满,因此进行一个判断语句
                    proWidth = proWidth < $('.progress').width() ? proWidth : $('.progress').width();
                }, 1000);
            })

最终就能获得这样的效果

html5音频 js控制 js控制音乐播放_进度条_05