HTML5 CSS3实战——自定义音乐播放器(一)

时间:2021-04-15 10:15:56

前几天才刚开始接触HTML5和CSS3。学习了一下里面的一些炫酷的新特性。不过,对于原生的HTML5的媒体播放器,真的不得不吐槽:就三个按钮 界面还那么丑。所以觉得自己整一个好看的播放器。老话说:说不如干,纸上谈兵终觉浅。所以结合这几天来学的东西,自己写了一个HTML5的播放器。
HTML5 CSS3实战——自定义音乐播放器(一)
HTML5原生播放器:
HTML5 CSS3实战——自定义音乐播放器(一)

我们的效果图:

HTML5 CSS3实战——自定义音乐播放器(一)

歌曲列表:

HTML5 CSS3实战——自定义音乐播放器(一)

首先分析下界面,将主面板解剖一下:
HTML5 CSS3实战——自定义音乐播放器(一)
整个界面都是用Html5的Canvas绘制的,切换歌曲的时候,中间的歌曲名和后面的专辑封面也会动态切换。默认顺序循环播放,就是一首接下一首,也可以切换成随机播放。

最上边的按钮是切换到歌曲列表面板;
中间的一排按钮,最左边的是顺序播放;
第二个是上一首;第三个是暂停/播放;
第四个是下一首;第五个是随机播放。
下面的是音量条,拖动控制音量;
最下面是歌词面板,点击后显示歌词。
最外边有一圈蓝色的进度条,提示歌曲当前播放进度。

代码实现:

主要的html5代码:

    <!--Music Box-->
    <div id="musicbox">
    <div id="container">
        <label class="to-back-label" for="to-back"><i class="fa fa-bars fa-lg"></i></label>
        <input type="checkbox" id="to-back"><!-- playlist toggle -->
        <canvas id="progress" width="320" height="320"></canvas><!-- progress bar -->
        <div id="player">
            <audio id="audio" controls>
            </audio>
            <img id="imcover" src="images/music/回梦游仙.png"><!-- album cover -->
            <label class="to-lyrics-label" for="to-lyrics"><i class="fa fa-caret-down fa-lg"></i></label>
            <input type="checkbox" id="to-lyrics"><!-- lyrics toggle -->

            <div class="cover">
                <div class="controls">
                    <div id="currentM" >正在播放:<strong id="rmusic">回梦游仙</strong></div>
                    <button id="randoms" title="随机播放"><i class="fa fa-retweet fa-lg"></i></button>
                    <button id="backward" title="上一首"><i class="fa fa-backward fa-2x"></i></button>
                    <button id="play-pause" title="Play" onclick="togglePlayPause()"><i class="fa fa-play fa-3x"></i></button>
                    <button id="forward" title="下一首"><i class="fa fa-forward fa-2x"></i></button>
                    <button id="sequence" title="顺序播放"><i class="fa fa-random fa-lg"></i></button>
                    <input id="volume" name="volume" min="0" max="1" step="0.1" type="range" onchange="setVolume()" />
                </div><!-- #controls -->
               <!-- <div class="info"> <p class="song"><a href="#" target="_blank">Abitude</a></p> <p class="author"><a href="#" target="_blank">Abi</a></p> </div><!-- #info -->
                <div id="lycs" class="lyrics">
                    <p>仙剑奇侠传4——回梦游仙.</p>
                    <p> 冰封的泪 如流星陨落</p>
                    <p> 跌碎了谁的思念</p>
                    <p> 轮回之间 前尘已湮灭</p>
                    <p> 梦中模糊容颜</p>
                    <p> 昆仑巅 江湖远 花谢花开花满天</p>
                    <p>叹红尘 落朱颜 天上人间</p>
                    <p>情如风 情如烟 琵琶一曲已千年</p>
                    <p>今生缘 来生缘 沧海桑田</p>
                    <p>成流年</p>

                    <p>古老的剑 斩断了宿怨</p>
                    <p>唤醒了谁的誓言</p>
                    <p>转瞬之间 隔世的爱恋</p>
                    <p>追忆往日缱绻</p>

                    <p>昆仑巅 浮生远 梦中只为你流连</p>
                    <p>笑红尘 画朱颜 浮云翩跹</p>
                    <p>情难却 情相牵 只羡鸳鸯不羡仙</p>
                    <p>今生缘 来生缘 难分难解</p>

                    <p>昆仑巅 浮生远 梦中只为你流连</p>
                    <p> 笑红尘 画朱颜 浮云翩跹</p>
                    <p> 情难却 情相牵 只羡鸳鸯不羡仙</p>
                    <p> 今生恋 来生恋 莫让缠绵 成离别</p>
                </div><!-- #lyrics -->
                <p class="scroll">scroll down</p>
            </div><!-- #cover -->
        </div><!-- #player -->
        <div id="flip-back">
            <ol class="playlist" id="playlist">
            </ol>

        </div><!-- #flip-back -->
    </div><!-- #container -->
    </div>
    <script type="text/javascript" src="js/musicbox.js"></script>

musicbox.js中的代码:

$(function() {

// 播放器
    var Player;
    Player = {
        // 歌曲路径
        path: 'video/',
        imgPath:'images/music/',
        // 歌曲数据
        data: null,
        imgs: null,

        // 当前播放歌曲的 索引
        currentIndex: -1,

        // 播放器元素jquery对象
        $audio: $('#audio'),

        // 歌曲列表
        $mList: $('#playlist'),

        //正在播放的歌曲
        $rmusic: $('#rmusic'),

        $cover:	 $('#imcover'),


        // 初始化 数据
        init: function () {

            // 数据一般来自服务器端,通过ajax 加载数据,这里是模拟
            //歌曲的数据
            Player.data = ['GlassySky.mp3', '回梦游仙.mp3', 'unravel.mp3','一直很安静.mp3'];
            //封面的数据
            Player.imgs = ['GlassySky.jpg', '回梦游仙.png', 'unravel.jpg','一直很安静.png'];
            Player.$rmusic.html(Player.data[Player.currentIndex]);
            //初始化
            var mhtml = '';
            var len = Player.data.length;
            //初始化歌曲列表
            for (var i = 0; i < len; i++) {
                mhtml += '<li value="' + i + '"><a >' + Player.data[i] + '</a></li>';

            }
            Player.$mList.html(mhtml);
            //初始化专辑封面
            Player.$cover.attr("src", Player.imgPath+Player.imgs[0]);
        },
        // 就绪
        ready: function () {
            // 控制

            Player.audio = Player.$audio.get(0);


                Player.$rmusic.html(Player.data[Player.currentIndex]);



            // 播放
            $('#btn-play').click(function () {
                Player.audio.play();
                if (Player.currentIndex == -1) {
                    $('#btn-next').click();
                }
            });

            // 暂停
            $('#btn-pause').click(function () {
                Player.audio.pause();
            });

            // 下一曲
            $("#forward").click(function () {
                if (Player.currentIndex == -1) {
                    Player.currentIndex = 0;
                } else if (Player.currentIndex == (Player.data.length - 1)) {
                    Player.currentIndex = 0;
                } else {
                    Player.currentIndex++;
                }
                var currentMusic=Player.data[Player.currentIndex];

                currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));

                console.log("Player.currentIndex : " + Player.currentIndex);
                Player.audio.src = Player.path + Player.data[Player.currentIndex];
                Player.$rmusic.html(currentMusic);
                Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
                Player.audio.play();
            });

            // 上一曲
            $('#backward').click(function () {
                if (Player.currentIndex == -1) {
                    Player.currentIndex = 0;
                } else if (Player.currentIndex == 0) {
                    Player.currentIndex = (Player.data.length - 1);
                } else {
                    Player.currentIndex--;
                }
                var currentMusic=Player.data[Player.currentIndex];

                currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));
                Player.audio.src = Player.path + Player.data[Player.currentIndex];
                Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
                Player.$rmusic.html(currentMusic);
                Player.audio.play();
            });

            // 单曲循环
            $('#btn-loop').click(function () {
                console.log("Player.currentIndex :", Player.currentIndex);
                Player.audio.onended = function () {
                    Player.audio.load();
                    Player.audio.play();
                };
            });

            // 顺序播放
            $('#sequence').click(function () {
                console.log("Player.currentIndex :", Player.currentIndex);
                Player.audio.onended = function () {
                    $('#btn-next').click();
                };
            });

            // 随机播放
            $('#randoms').click(function () {
                Player.audio.onended = function () {
                    var i = parseInt((Player.data.length - 1) * Math.random());
                    alert(i);
                    playByMe(i);
                };
            });

            // 播放指定歌曲
            function playByMe(i) {

                i=parseInt(i);
                Player.audio.src = Player.path + Player.data[i];
                Player.audio.play();
                Player.currentIndex = i;
                Player.$rmusic.html(Player.data[Player.currentIndex]);
                Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
            }


            // 歌曲被点击
                $('#playlist li').click(function () {
                    $(this).find('a').find('i').remove();
                    $(this).find('a').css("color","#26C5CB");
                    $(this).find('a').prepend("<i class=\"fa fa-play\" style=\"margin-right:4px;\"></i>");
                    $(this).siblings().find('a').css("color","#ffffff");
                    $(this).siblings().find('a').find('i').remove();
                    var i = parseInt($(this).attr('value'));
                    playByMe(i);
                    /*style="color:#26C5CB;"*/
                });





        },
        //循环播放
        loop:function(){
            Player.audio.onended = function(){
                if (Player.currentIndex == -1) {
                    Player.currentIndex = 0;
                } else if (Player.currentIndex == (Player.data.length - 1)) {
                    Player.currentIndex = 0;
                } else {
                    Player.currentIndex++;
                }
                var currentMusic=Player.data[Player.currentIndex];

                currentMusic = currentMusic.substring(0,currentMusic.indexOf('.'));

                console.log("Player.currentIndex : " + Player.currentIndex);
                Player.audio.src = Player.path + Player.data[Player.currentIndex];
                Player.$cover.attr("src", Player.imgPath+Player.imgs[Player.currentIndex]);
                Player.$rmusic.html(currentMusic);
                Player.audio.play();
            }

        }

    };

    Player.init();
    Player.ready();
    Player.loop();

});






audio.controls = false;

audio.addEventListener('timeupdate', function() {
    updateProgress();
}, false);

function togglePlayPause() {
   if (audio.paused || audio.ended) {
      playpause.title = "Pause";
      playpause.innerHTML = '<i class="fa fa-pause fa-3x"></i>';
      audio.play();
   } else {
      playpause.title = "Play";
      playpause.innerHTML = '<i class="fa fa-play fa-3x"></i>';
      audio.pause();
   }
}

function setVolume() {
   audio.volume = volume.value;
}
//更新进度条
function updateProgress() {
    var percent = Math.floor((100 / audio.duration) * audio.currentTime);
    progress.value = percent;
    var canvas = document.getElementById('progress');
    var context = canvas.getContext('2d');
    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;
    var radius = 150;
    var circ = Math.PI * 2;
    var quart = Math.PI / 2;
    var cpercent = percent / 100; /* current percent */
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, ((circ) * cpercent), false);
    context.lineWidth = 10;
    context.strokeStyle = '#26C5CB';
    context.stroke();
    if (audio.ended) resetPlayer();
}
//重置播放器
function resetPlayer() {
      audio.currentTime = 0; context.clearRect(0,0,canvas.width,canvas.height);
  playpause.title = "Play";
      playpause.innerHTML = '<i class="fa fa-play fa-3x"></i>';
}

由于时间关系,所以歌词列表的动态显示功能还没做。这需要解析歌词的格式。准备在下次完成歌词列表功能。