您现在的位置:首页 >> 前端 >> 内容

一步一步实战HTML音乐播放器

时间:2017/2/24 22:22:00 点击:

  核心提示:一步一步实战HTML音乐播放器,在这里我用HTML5从头开始一步一步来制作一个简约的音乐播放器,大家可以参考一下,接下来正式开始。音乐播放器效果 播放器分析这里将播放器分两块来做:视图层(html +...
一步一步实战HTML音乐播放器,在这里我用HTML5从头开始一步一步来制作一个简约的音乐播放器,大家可以参考一下,接下来正式开始。

音乐播放器效果

一步一步实战HTML音乐播放器

播放器分析

这里将播放器分两块来做:

视图层(html + css) 逻辑层 ( js )

视图层分析

视图中包含:

播放器容器 

播放器名称 音乐专辑图 音乐信息 

歌曲名 歌手 专辑名 控制区 

上一曲 播放 下一曲 播放进度条 播放时间 

当前时间 歌曲总时间 音频控件 页面背景

逻辑层分析

逻辑层处理包括:

加载歌单 渲染歌曲信息 

专辑图 歌曲名 歌手 专辑名 歌曲时长 歌曲音频地址 监听控制按钮 

播放按钮 (修改播放状态) 上一曲(判断歌单边界,重新渲染歌曲信息) 下一曲(判断歌单边界,重新渲染歌曲信息) 定时器 

同步歌曲当前时间和播放进度条 歌曲播放完,自动切换下一曲

好了,播放器基本分析完成,接下来开始编码了,先进行视图层的编写。

视图层结构编写

根据我在上面的视图层分析,来构建HTML结构。

建立index.html,结构编码如下:

<!-- 页面背景 -->

<body>

    <!-- 播放器容器 -->

    <p class="player">

        <!-- 播放器名称 -->

        <p class="header">音乐播放器</p>

        <!-- 音乐专辑图 -->

        <p class="albumPic"></p>

        <!-- 音乐信息  -->

        <p class="trackInfo">

            <!-- 歌曲名 -->

            <p class="name"></p>

            <!-- 歌手 -->

            <p class="artist"></p>

            <!-- 专辑名 -->

            <p class="album"></p>

        </p>

        <!-- 播放进度条 -->

        <p class="progress"></p>

        <!-- 控制区  -->

        <p class="controls">

            <!-- 播放 -->

            <p class="play">

                <i class="icon-play"></i>

            </p>

            <!-- 上一曲 -->

            <p class="previous">

                <i class="icon-previous"></i>

            </p>

            <!-- 下一曲 -->

            <p class="next">

                <i class="icon-next"></i>

            </p>

        </p>      

        <!-- 播放时间  -->

        <p class="time">

            <!-- 当前时间 -->

            <p class="current"></p>

            <!-- 歌曲总时间 -->

            <p class="total"></p>

        </p>

        <!-- 音频控件 -->

        <audio id="audio"><source src=""></audio>

    </p>

</body>

好了,结构编写完毕,接下来编写视图层样式。

视图层样式编写

注:这里我是用LESS写的CSS,后面我会贴出完整代码,或者到 CSDN CODE 下载源码

先重置标记样式:

html, body, p, span, applet, object, iframe,

h1, h2, h3, h4, h5, h6, p, blockquote, pre,

a, abbr, acronym, address, big, cite, code,

del, dfn, em, img, ins, kbd, q, s, samp,

small, strike, strong, sub, sup, tt, var,

b, u, i, center,

dl, dt, dd, ol, ul, li,

fieldset, form, label, legend,

table, caption, tbody, tfoot, thead, tr, th, td,

article, aside, canvas, details, embed, 

figure, figcaption, footer, header, hgroup, 

menu, nav, output, ruby, section, summary,

time, mark, audio, video {

    margin: 0;

    padding: 0;

    border: 0;

    font-size: 100%;

    font: inherit;

    vertical-align: baseline;

}

/* HTML5 display-role reset for older browsers */

article, aside, details, figcaption, figure, 

footer, header, hgroup, menu, nav, section {

    display: block;

}

body {

    line-height: 1;

}

ol, ul {

    list-style: none;

}

blockquote, q {

    quotes: none;

}

blockquote:before, blockquote:after,

q:before, q:after {

    content: '';

    content: none;

}

table {

    border-collapse: collapse;

    border-spacing: 0;

}

设置body:

<script type="text/javascript" src="js/jquery.min.js"></script>

<script type="text/javascript" src="js/playlist.js"></script>

playlist.js就是一堆json的歌单数据,数据是从网易云音乐上获取的,基本内容如下:

//因为做静态页有跨域问题,所以就直接把数据拿出来赋值给`playlist`这个对象上了,下面只保留了需要用到的数据对象

var playlist = {

    "result": {

        "tracks": [

            {

                "name": "歌曲名",

                "artists": [

                    {

                        "name": "演唱者",

                    }

                ],

                "album": {

                    "name": "专辑名",

                    "picUrl":专辑图",

                "duration": 时长(ms),

                "mp3Url": "音乐地址"

            },

            ...//等等等

        ],

    },

};

网易云音乐歌单json数据接口:https://music.163.com/api/playlist/detail?id=xxx

建立index.js,开始编码:

先定义一个播放状态对象playStatus:

//当前播放器状态

var playStatus = {

    currentTrackLen: playlist.result.tracks.length, //歌单歌曲数

    currentTrackIndex: 0, //当前播放的歌曲索引,默认加载第一首歌

    currentTime: 0, //当前歌曲播放的时间

    currentTotalTime: 0, //当前歌曲的总时间

    playStatus: true, //true为播放状态,false为暂停状态

};

因为要用到时间的转换,所以编写一个时间转换函数:

var timeConvert = function(timestamp){

    var minutes = Math.floor(timestamp / 60);

    var seconds = Math.floor(timestamp - (minutes * 60));

    if(seconds < 10) {

      seconds = '0' + seconds;

    }

    timestamp = minutes + ':' + seconds;

    return timestamp;

};

接下来编写一个对象,内部方法是控制播放器的:

//播放器控制方法对象

var playerControls = {

    //歌曲基本信息设置

    trackInfo: function(args){

        //playerlist是playlist.js中的歌单数据,根据需求进行数据读取即可

        var obj = playlist.result.tracks[playStatus.currentTrackIndex];

        args = args || {

            name:obj.name,

            artist:obj.artists[0].name,

            album:obj.album.name,

            albumPic:obj.album.picUrl + '?param=270y270',

            total:obj.duration,

            src: obj.mp3Url,

        };

        $('.player .trackInfo .name').text(args.name);

        $('.player .trackInfo .artist').text(args.artist);

        $('.player .trackInfo .album').text(args.album);   

        $('.player .albumPic').css('background','url(' + args.albumPic + ')');         

        $('.player .time .total').text(timeConvert(args.total / 1000)); //因为歌单数据中的播放长度用ms表示的,所以这里 / 1000

        playStatus.currentTotalTime = Math.floor(args.total / 1000);

        $('#audio source').attr('src',args.src); //切换音乐通过修改<source>中的src

    },

    //播放、暂停状态处理

    playStatus: function(){

        $('.player .controls .play i').attr('class', 'icon-' + (playStatus.playStatus?'pause':'play'));

        if(playStatus.playStatus){

            //用jquery获取<audio>对象,必须加上[0]

            $('#audio')[0].play();

        }else{

            $('#audio')[0].pause();

        }

    },

    //当前时间和进度处理

    playTime: function(){

        $('.player .time .current').text(timeConvert(playStatus.currentTime));

        $('.player .progress').css('width', playStatus.currentTime / playStatus.currentTotalTime * 100 + '%'); //同步进度条

    }

};

还剩下一个初始化方法了:

var init = function(){

    //置一下歌曲信息和播放状态

    playerControls.trackInfo();     

    playerControls.playStatus();

    //播放按钮事件监听

    $('.player .controls .play').click(function(){

        //修改播放状态

        playStatus.playStatus = !playStatus.playStatus; 

        //置播放信息

        playerControls.playStatus();

    });

    //上一曲按钮事件监听

    $('.player .controls .previous').click(function(){

        //边界判断

        if(playStatus.currentTrackIndex - 1 < 0){

            alert('已经没有上一首了');

        }else{

            playStatus.currentTrackIndex --;

        }

        //此处切换歌曲功能,原来打算采用直接修改src的方法实现,但是修改src后,之前播放的音乐还继续播放着,切换后的音乐却不播放,所以最终采用移除<audio>,再加入<audio>的方式来切换音乐

        $('#audio').remove();

        $('.player').append('<audio id="audio"><source src=""></audio>');  

        //更新音轨信息和播放状态       

        playerControls.trackInfo();

        playerControls.playStatus();

    });

    //下一曲按钮事件监听

    $('.player .controls .next').click(function(){

        if(playStatus.currentTrackIndex + 1 >= playStatus.currentTrackLen){

            alert('已经没有下一首了');

        }else{

            playStatus.currentTrackIndex ++;

        }

        //换src的方法没法切换声音,试了好几种方法都不行,只能删了再重建了

        $('#audio').remove();

        $('.player').append('<audio id="audio"><source src=""></audio>');          

        playerControls.trackInfo();

        playerControls.playStatus();

    });

    //用时钟来实时修改当前播放时间及播放完当前曲目自动下一曲

    setInterval(function(){

        playStatus.currentTime = $('#audio')[0].currentTime;           

        playerControls.playTime();

        if(playStatus.currentTime >= playStatus.currentTotalTime){

            $('.player .controls .next').click();

        }

    }, 300);

};

其后,再加入init()执行一下就OK了。

完整代码

index.html:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>H5音乐播放器</title>

    <link rel="stylesheet" type="text/css" href="css/index.css">

    <script type="text/javascript" src="js/jquery.min.js"></script>

    <script type="text/javascript" src="js/playlist.js"></script>

    <script type="text/javascript" src="js/index.js"></script>

</head>

<body>

    <p class="player">

        <p class="header">音乐播放器</p>

        <p class="albumPic"></p>

        <p class="trackInfo">

            <p class="name"></p>

            <p class="artist"></p>

            <p class="album"></p>

        </p>

        <p class="progress"></p>

        <p class="controls">

            <p class="play">

                <i class="icon-play"></i>

            </p>

            <p class="previous">

                <i class="icon-previous"></i>

            </p>

            <p class="next">

                <i class="icon-next"></i>

            </p>

        </p>      

        <p class="time">

            <p class="current"></p>

            <p class="total"></p>

        </p>

        <audio id="audio"><source src=""></audio>

    </p>

</body>

</html>

index.css:

@import 'reset.css';

@import 'fonts.css';

html,

body {

  height: 100%;

}

body {

  background-color: #111111;

  display: -webkit-box;

  display: -webkit-flex;

  display: -ms-flexbox;

  display: flex;

  -webkit-box-align: center;

  -webkit-align-items: center;

      -ms-flex-align: center;

          align-items: center;

  -webkit-box-pack: center;

  -webkit-justify-content: center;

      -ms-flex-pack: center;

          justify-content: center;

  color: #fff;

  font: 16px "微软雅黑";

}

.player {

  width: 375px;

  height: 550px;

  background-color: #2b2b2b;

  border-radius: 10px;

  position: relative;

}

.player .header {

  padding: 15px 0;

  text-align: center;

}

.player .albumPic {

  background-size: cover;

  width: 270px;

  height: 270px;

  margin: auto;

  border-radius: 10px;

}

.player .trackInfo {

  text-align: center;

  padding: 20px 0 15px;

  font-size: 14px;

  white-space: nowrap;

}

.player .trackInfo .name {

  font-size: 24px;

  margin-bottom: 10px;

  font-weight: bold;

}

.player .progress {

  width: 0;

  height: 20%;

  position: absolute;

  bottom: 0;

  left: 0;

  background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0), #0099ff);

  background-image: linear-gradient(top, rgba(255, 255, 255, 0), #0099ff);

  border-bottom-left-radius: 10px;

  border-bottom-right-radius: 10px;

  opacity: .4;

}

.player .controls {

  position: relative;

}

.player .controls .play {

  cursor: pointer;

  width: 75px;

  height: 75px;

  border: 2px solid #ccc;

  border-radius: 50%;

  margin: auto;

  display: -webkit-box;

  display: -webkit-flex;

  display: -ms-flexbox;

  display: flex;

  -webkit-box-align: center;

  -webkit-align-items: center;

      -ms-flex-align: center;

          align-items: center;

  -webkit-box-pack: center;

  -webkit-justify-content: center;

      -ms-flex-pack: center;

          justify-content: center;

  color: #fff;

  font-size: 35px;

}

.player .controls .play:hover {

  font-size: 40px;

}

.player .controls .previous {

  cursor: pointer;

  position: absolute;

  top: 25px;

  font-size: 30px;

  left: 60px;

}

.player .controls .previous:hover {

  font-size: 32px;

}

.player .controls .next {

  cursor: pointer;

  position: absolute;

  top: 25px;

  font-size: 30px;

  right: 60px;

}

.player .controls .next:hover {

  font-size: 32px;

}

.player .time {

  width: 335px;

  display: -webkit-box;

  display: -webkit-flex;

  display: -ms-flexbox;

  display: flex;

  position: absolute;

  bottom: 0;

  padding: 20px;

  -webkit-box-align: center;

  -webkit-align-items: center;

      -ms-flex-align: center;

          align-items: center;

  -webkit-box-pack: justify;

  -webkit-justify-content: space-between;

      -ms-flex-pack: justify;

          justify-content: space-between;

}

index.js:

$().ready(function(){

    //当前播放器状态

    var playStatus = {

        currentTrackLen: playlist.result.tracks.length,

        currentTrackIndex: 0,

        currentTime: 0,

        currentTotalTime: 0,

        playStatus: true,

    };

    //播放器控制方法

    var playerControls = {

        //歌曲基本信息

        trackInfo: function(args){

            var obj = playlist.result.tracks[playStatus.currentTrackIndex];

            args = args || {

                name:obj.name,

                artist:obj.artists[0].name,

                album:obj.album.name,

                albumPic:obj.album.picUrl + '?param=270y270',

                total:obj.duration,

                src: obj.mp3Url,

            };

            $('.player .trackInfo .name').text(args.name);

            $('.player .trackInfo .artist').text(args.artist);

            $('.player .trackInfo .album').text(args.album);   

            $('.player .albumPic').css('background','url(' + args.albumPic + ')');         

            $('.player .time .total').text(timeConvert(args.total / 1000));

            playStatus.currentTotalTime = Math.floor(args.total / 1000);

            $('#audio source').attr('src',args.src);

        },

        //播放、暂停状态处理

        playStatus: function(){

            $('.player .controls .play i').attr('class', 'icon-' + (playStatus.playStatus?'pause':'play'));

            if(playStatus.playStatus){

                $('#audio')[0].play();

            }else{

                $('#audio')[0].pause();

            }

        },

        //当前时间和进度处理

        playTime: function(){

            $('.player .time .current').text(timeConvert(playStatus.currentTime));

            $('.player .progress').css('width', playStatus.currentTime / playStatus.currentTotalTime * 100 + '%');

        }

    };

    var timeConvert = function(timestamp){

        var minutes = Math.floor(timestamp / 60);

        var seconds = Math.floor(timestamp - (minutes * 60));

        if(seconds < 10) {

          seconds = '0' + seconds;

        }

        timestamp = minutes + ':' + seconds;

        return timestamp;

    };

    (function(){

        playerControls.trackInfo();     

        playerControls.playStatus();

        $('.player .controls .play').click(function(){

            playStatus.playStatus = !playStatus.playStatus; 

            playerControls.playStatus();

        });

        $('.player .controls .previous').click(function(){

            if(playStatus.currentTrackIndex - 1 < 0){

                alert('已经没有上一首了');

            }else{

                playStatus.currentTrackIndex --;

            }

            $('#audio').remove();

            $('.player').append('<audio id="audio"><source src=""></audio>');          

            playerControls.trackInfo();

            playerControls.playStatus();

        });

        $('.player .controls .next').click(function(){

            if(playStatus.currentTrackIndex + 1 >= playStatus.currentTrackLen){

                alert('已经没有下一首了');

            }else{

                playStatus.currentTrackIndex ++;

            }

            //换src的方法没法切换声音,试了好几种方法都不行,只能删了再重建了

            $('#audio').remove();

            $('.player').append('<audio id="audio"><source src=""></audio>');          

            playerControls.trackInfo();

            playerControls.playStatus();

        });

        setInterval(function(){

            playStatus.currentTime = $('#audio')[0].currentTime;           

            playerControls.playTime();

            if(playStatus.currentTime >= playStatus.currentTotalTime){

                $('.player .controls .next').click();

            }

        }, 300);

    })();

});

 

作者:网络 来源:王乐平 技术博客