项目资料

查看源码 在线Demo

基本框架及顶部布局

<div class="header"><h1 class="logo"><a href="#"></a></h1><ul class="register"><li>注册</li><li>登陆</li></ul>
</div>
<div class="content"><div class="content_in"></div>
</div>
<div class="footer"><div class="footer_in"></div>
</div>
* {margin: 0;padding: 0;
}
.header {width: 100%;height: 45px;background: red;
}
.header .logo {float: left;margin-left: 20px;opacity: 0.5;
}
.header .logo:hover {opacity: 1;
}
.header .logo a {display: inline-block;width: 78px;height: 21px;background: url("../images/player_logo.png") no-repeat 0 0;
}
.header .register {float: right;line-height: 25px;
}
.header .register li {list-style: none;float: left;margin-right: 20px;color: #fff;opacity: 0.5;cursor: pointer;
}
.header .register li:hover {opacity: 1;
}
.content {width: 100%;height: 460px;background: blue;
}
.content .content_in {width: 1200px;height: 100%;background: deeppink;margin: 0 auto;
}
.footer {width: 100%;height: 60px;background: green;position: absolute;bottom: 0;left: 0;
}
.footer .footer_in {width: 1200px;height: 100%;background: plum;margin: 0 auto;
}

工具条

工具条使用span作为按钮,里边为图片加文字。

<div class="content_in"><div class="content_left"><div class="content_toolbar"><span><i></i>收藏</span><span><i></i>添加到</span><span><i></i>下载</span><span><i></i>删除</span><span><i></i>清空列表</span></div></div>
</div>
.content .content_in .content_left {float: left;width: 800px;height: 100%;background: pink;
}
.content_left .content_toolbar {width: 100%;height: 40px;background: #000;
}
.content_toolbar span {display: inline-block;width: 122px;height: 100%;line-height: 40px;text-align: center;box-sizing: border-box;border: 1px solid #fff;color: #fff;opacity: 0.5;cursor: pointer;
}
.content_toolbar span:hover {opacity: 1;
}
.content_toolbar span i {display: inline-block;width: 18px;height: 18px;background: url("../images/icon_sprite.png") no-repeat;margin-right: 10px;vertical-align: -5px;
}
.content_toolbar span:nth-child(1) i {background-position: -60px -20px;
}
.content_toolbar span:nth-child(2) i {background-position: -20px -20px;
}
.content_toolbar span:nth-child(3) i {background-position: -40px -240px;
}
.content_toolbar span:nth-child(4) i {background-position: -100px -20px;
}
.content_toolbar span:nth-child(5) i {background-position: -40px -300px;
}

歌曲列表

歌曲列表可以视作逐行的列表,第一行为标题,下边为歌曲。

<div class="content_left"><div class="content_list"><ul><li class="list_title"><div class="list_check"><i></i></div><div class="list_number"></div><div class="list_name">歌曲</div><div class="list_singer">歌手</div><div class="list_time">时长</div></li><li class="list_music"><div class="list_check"><i></i></div><div class="list_number">1</div><div class="list_name">哈哈哈</div><div class="list_singer">TZK</div><div class="list_time">03:17</div></li></ul></div>
</div>
/* TAG 播放列表布局 */
.content_list li {list-style: none;width: 100%;height: 50px;background: orangered;border: 1px solid rgba(255, 255, 255, 0.5);box-sizing: border-box;
}
.content_list li div {float: left;color: #fff;text-align: 50px;opacity: 0.5;
}
.content_list .list_check {width: 50px;height: 100%;background: #000;text-align: center;
}
.content_list .list_check i {display: inline-block;width: 14px;height: 14px;border: 1px solid #000;
}
.content_list .list_number {width: 20px;height: 100%;background: green;
}
.content_list .list_name {width: 50%;height: 100%;background: #ccc;
}
.content_list .list_singer {width: 20%;height: 100%;background: pink;
}

完善播放列表

  1. 选择框

    伪选择框,使用图片,当被点击时,切换图片

  2. 鼠标悬停的图标

    使用a标签加背景图即可。使用jQuery监听鼠标的移入移出事件。

<li class="list_music"><div class="list_check"><i></i></div><div class="list_number">1</div><div class="list_name">哈哈哈<div class="list_menu"><a href="javascript:;" title="播放"></a><a href="javascript:;" title="添加"></a><a href="javascript:;" title="下载"></a><a href="javascript:;" title="分享"></a></div></div><div class="list_singer">TZK</div><div class="list_time"><span>04:12</span><a href="javascript:;" title="删除"></a></div>
</li>
.list_name .list_menu {margin-top: 5px;float: right;margin-right: 20px;display: none;
}
.list_name .list_menu a {display: inline-block;width: 36px;height: 36px;background: url("../images/icon_list_menu.png") no-repeat 0 0;
}
.list_name .list_menu a:nth-child(1) {background-position: -120px 0;
}
.list_name .list_menu a:nth-child(2) {background-position: -120px -80px;
}
.list_name .list_menu a:nth-child(3) {background-position: -120px -120px;
}
.list_name .list_menu a:nth-child(4) {background-position: -120px -40px;
}
.content_list .list_time a {display: inline-block;width: 36px;height: 36px;background: url("../images/icon_list_menu.png") no-repeat -120px -160px;float: left;margin-top: 5px;display: none;
}
$(function () {// 1. 监听歌曲的移入移出事件$(".list_music").hover(function () {//   显示子菜单$(this).find(".list_menu").stop().fadeIn(100);$(this).find(".list_time a").stop().fadeIn(100);//   隐藏时长$(this).find(".list_time span").stop().fadeOut(100);},function () {//   隐藏子菜单$(this).find(".list_menu").stop().fadeOut(100);$(this).find(".list_time a").stop().fadeOut(100);//   显示时长$(this).find(".list_time span").stop().fadeIn(100);});// 2. 监听复选框的点击事件$(".list_check").click(function () {$(this).toggleClass("list_checked");});
});

自定义滚动条

自定义滚动条使用了一个jQuery插件jQuery custom content scroller。利用这个插件可以轻松设置滚动条样式。

  1. 引入CSS文件

  2. 在jQuery下方引入JS文件

  3. 为需要添加的元素调用mCustomScrollbar()方法

    $(".content_list").mCustomScrollbar();
    
  4. 为该元素添加自定义属性data-mcs-theme="dark"

    <div class="content_list" data-mcs-theme='minimal-dark'></div>
    
  5. 小细节(修改其默认样式)

    根据图中所示,可以将滚动条的宽度增加。

    /* 滚动条 */
    ._mCS_1 .mCSB_scrollTools .mCSB_dragger_bar {width: 8px;
    }
    

音乐歌曲信息

<div class="content_right"><div class="song_info"><a href="javascript;;" class="song_info_pic"><img src="data:images/lnj.jpg" alt=""></a><div class="song_info_name">歌曲名称:<a href="javascript:;">xiaokang</a></div><div class="song_info_singer">歌手名:<a href="javascript:;">xiaokang</a></div><div class="song_info_ablum">专辑名:<a href="javascript:;">xiaokang</a></div></div><ul class="song_lyric"><li class="cur">第一条歌词</li><li>第二条歌词</li></ul>
</div>
.content_right .song_info {text-align: center;color: rgba(255, 255, 255, 0.5);line-height: 30px;
}.song_info .song_info_pic {display: inline-block;background: url("../images/album_cover_player.png") no-repeat 0 0;width: 201px;height: 180px;text-align: left;
}
.song_info_pic img {width: 180px;height: 180px;
}
.song_info div a {text-decoration: none;color: #fff;opacity: 0.5;
}
.song_info div a:hover {opacity: 1;
}
.content_right .song_lyric {background: gray;text-align: center;margin-top: 30px;
}
.content_right .song_lyric li {list-style: none;line-height: 30px;color: rgba(255, 255, 255, 0.5);font-weight: bold;
}
.content_right .song_lyric .cur {color: #31c27c;
}

底部结构

基本结构

进度条可大致分为四部分

  1. 图标

    使用a标签加背景图即可

  2. 歌曲进度条(红色区域)

    因为此区域需包含进度条及歌曲名称、时间等信息。因此使用div作为布局

  3. 音量部分(绿色区域)

    此部分包含图标及一个拖动条,因此也使用div作为盒子进行布局。

<div class="footer_in"><a href="javascript:;" class="music_pre"></a><a href="javascript:;" class="music_play"></a><a href="javascript:;" class="music_next"></a><div class="music_progress_info"></div><a href="javascript:;" class="music_mode"></a><a href="javascript:;" class="music_fav"></a><a href="javascript:;" class="music_down"></a><a href="javascript:;" class="music_comment"></a><a href="javascript:;" class="music_only"></a><div class="music_voice_info"></div>
</div>
.footer_in a {display: inline-block;text-decoration: none;color: #fff;background: url("../images/player.png") no-repeat 0 0;margin-right: 20px;
}
.footer_in .music_pre {width: 19px;height: 20px;background-position: 0 -30px;
}
.footer_in .music_play {width: 21px;height: 29px;background-position: 0 0;
}
.footer_in .music_next {width: 19px;height: 20px;background-position: 0 -52px;
}
.footer_in .music_progress_info {display: inline-block;width: 670px;height: 40px;background-color: red;
}
.footer_in .music_mode {width: 26px;height: 25px;background-position: 0px -205px;
}
.footer_in .music_fav {width: 24px;height: 21px;background-position: 0px -96px;
}
.footer_in .music_down {width: 22px;height: 21px;background-position: 0px -120px;
}
.footer_in .music_comment {width: 24px;height: 24px;background-position: 0px -400px;
}
.footer_in .music_only {width: 74px;height: 27px;background-position: 0px -281px;
}
.footer_in .music_voice_info {display: inline-block;width: 100px;background: green;height: 40px;
}

进度条

  1. 歌曲部分的结构

    • 信息部分

      两个span元素即可

    • 进度条

      一种通用的结构。三层结构分别表示背景、前景、圆。

      <div class="music_progress_bar"><div class="music_progress_line"><div class="music_progress_dot"></div></div>
      </div>
      

  2. 音量部分

    与歌曲信息的进度条同理,图标同样使用a标签与图片结合。

<div class="music_progress_info"><div class="music_progress_top"><span class="music_progress_name">666/666</span><span class="music_progress_time">00:00 / 05:23</span></div><div class="music_progress_bar"><div class="music_progress_line"><div class="music_progress_dot"></div></div></div>
</div>
<div class="music_voice_info"><a href="javascript:;" class="music_voice_icon"></a><div class="music_voice_bar"><div class="music_voice_line"><div class="music_voice_dot"></div></div></div>
</div>
/* 歌曲进度条 */
.footer_in .music_progress_info {display: inline-block;width: 670px;height: 40px;background-color: red;
}
.music_progress_info .music_progress_top {width: 100%;height: 30px;line-height: 30px;background: #000000;color: #fff;
}
.music_progress_top .music_progress_name {float: left;opacity: 0.5;
}
.music_progress_top .music_progress_name:hover {opacity: 1;
}
.music_progress_top .music_progress_time {float: right;opacity: 0.5;
}.music_progress_info .music_progress_bar {width: 100%;height: 4px;background: rgba(255, 255, 255, 0.5);margin-top: 5px;
}
.music_progress_bar .music_progress_line {width: 100%;height: 100%;background: #ffffff;
}
.music_progress_bar .music_progress_dot {width: 14px;height: 14px;border-radius: 50%;background: #fff;position: relative;top: -5px;left: 100px;cursor: pointer;
}
/* 音量控制 */
.footer_in .music_voice_info {display: inline-block;width: 100px;background: green;height: 40px;position: relative;
}
.music_voice_info .music_voice_icon {width: 26px;height: 21px;background-position: 0 -144px;position: absolute;left: 0;top: 10px;
}
.music_voice_info .music_voice_bar {width: 70px;height: 4px;background: rgba(255, 255, 255, 0.5);position: absolute;right: 0;top: 18px;
}
.music_voice_bar .music_voice_line {width: 50px;height: 100%;background: #ffffff;
}
.music_voice_bar .music_voice_dot {width: 14px;height: 14px;border-radius: 50%;background: #ffffff;position: absolute;top: -5px;left: 50px;
}

底部微调完善

.footer {height: 80px;
}
.footer_in .music_play {vertical-align: -5px;
}
.footer_in .music_progress_info {top: 10px;
}
.footer_in .music_voice_info {top: 10px;
}
/* 播放按钮点击 */
.footer_in .music_play2 {background-position: -30px 0;
}
/* 循环模式样式切换 */
.footer_in .music_mode2 {width: 23px;height: 20px;background-position: 0px -260px;
}
.footer_in .music_mode3 {width: 25px;height: 19px;background-position: 0px -74px;
}
.footer_in .music_mode4 {width: 26px;height: 25px;background-position: 0px -232px;
}
/* 喜欢按钮 */
.footer_in .music_fav2 {background-position: -30px -96px;
}
/* 纯净模式 */
.footer_in .music_only2 {background-position: 0px -310px;
}

高斯模糊背景

模糊背景通过使用一张图加一个淡灰色的蒙版即可。

<div class="footer"></div>
<div class="mask_bg"></div>
<div class="mask"></div>
/* 背景设置 */
.mask_bg {position: absolute;left: 0;top: 0;width: 100%;height: 100%;background: url("../images/lnj.jpg") no-repeat 0 0;background-size: cover;z-index: -2;filter: blur(100px);
}
.mask {position: absolute;left: 0;top: 0;width: 100%;height: 100%;z-index: -1;background: rgba(0, 0, 0, 0.35);
}

加载歌曲

加载歌曲使用了jQuery得Ajax方法。通过一个json文件获取歌曲的相关信息。

// 3. 加载歌曲列表
function getPlayerList() {$.ajax({url: "./source/musiclist.json",dataType: "json",success: function (data) {// 3.1 遍历获取到的数据创建每一条音乐var $musicList = $(".content_list ul");$.each(data, function (index, ele) {var $item = createMusicItem(index, ele);$musicList.append($item);});},error: function (e) {console.log(e);},});
}
getPlayerList();
// 创建一条音乐的方法
function createMusicItem(index, music) {var $item = $('<li class="list_music"><div class="list_check "><i></i></div><div class="list_number">' +(index + 1) +'</div><div class="list_name">' +music.name +'<div class="list_menu"><a href="javascript:;" title="播放"></a><a href="javascript:;" title="添加"></a><a href="javascript:;" title="下载"></a><a href="javascript:;" title="分享"></a></div></div><div class="list_singer">' +music.singer +'</div><div class="list_time"><span>' +music.time +'</span><a href="javascript:;" title="删除"></a></div></li>');return $item;
}

完善事件

由于音乐列表改成了js动态创建,那么就会导致曾经绑定的事件失效,因此需要修改为事件委托方式。

// 1. 监听歌曲的移入移出事件
$(".content_list").delegate(".list_music", "mouseenter", function () {//   显示子菜单$(this).find(".list_menu").stop().fadeIn(100);$(this).find(".list_time a").stop().fadeIn(100);//   隐藏时长$(this).find(".list_time span").stop().fadeOut(100);
});
$(".content_list").delegate(".list_music", "mouseleave", function () {//   隐藏子菜单$(this).find(".list_menu").stop().fadeOut(100);$(this).find(".list_time a").stop().fadeOut(100);//   显示时长$(this).find(".list_time span").stop().fadeIn(100);
});// 2. 监听复选框的点击事件
$(".content_list").delegate(".list_check", "click", function () {$(this).toggleClass("list_checked");
});

音乐播放图标切换

为此按钮添加事件同样需要以事件委托的方式。当点击后会发生两件事:

  1. 将其他播放按钮改为暂停状态
  2. 将底部播放按钮修改
// 3. 添加子菜单播放按钮的监听
var $musicPlay = $(".music_play");
$(".content_list").delegate(".list_menu_play", "click", function () {// 3.1 切换播放的图标$(this).toggleClass("list_menu_play2");// 3.2 复原其他的播放图标$(this).parents(".list_music").siblings().find(".list_menu_play").removeClass("list_menu_play2");// 3.3 同步底部播放按钮if ($(this).attr("class").indexOf("list_menu_play2") != -1) {// 当前是播放状态$musicPlay.addClass("music_play2");} else {$musicPlay.removeClass("music_play2");}
});

音乐播放状态切换

要想控制单个,必须设置时对单个设置,而不是全部,因此css部分需要微调。

.content_list li div {color: rgba(255, 255, 255, 0.5);
}
.content_list .list_check i {opacity: 0.5;
}
.content_list .list_checked i {opacity: 1;
}
.list_name .list_menu a {opacity: 0.5;
}
.list_name .list_menu a:hover {opacity: 1;
}
.content_list .list_time a {opacity: 0.5;
}
.content_list .list_time a:hover {opacity: 1;
}

将css修改完成后,接下来就是在JavaScript绑定的事件中进行修改了。

// 3.3 同步底部播放按钮
if ($(this).attr("class").indexOf("list_menu_play2") != -1) {// 当前是播放状态$musicPlay.addClass("music_play2");// 让文字高亮$(this).parents(".list_music").find("div").css("color", "#fff");
} else {$musicPlay.removeClass("music_play2");// 让文字不高亮$(this).parents(".list_music").find("div").css("color", "rgba(255,255,255,0.5)");
}

序号动画

动画采用图片的方式实现。当点击时,因此文字,并且显示图片。并作一些排他设置。

$(".content_list").delegate(".list_menu_play", "click", function () {var $item = $(this).parents(".list_music");// 3.1 切换播放的图标$(this).toggleClass("list_menu_play2");// 3.2 复原其他的播放图标$(this).parents(".list_music").siblings().find(".list_menu_play").removeClass("list_menu_play2");// 3.3 同步底部播放按钮if ($(this).attr("class").indexOf("list_menu_play2") != -1) {// 当前是播放状态$musicPlay.addClass("music_play2");// 让文字高亮$item.find("div").css("color", "#fff");$item.siblings().find("div").css("color", "rgba(255,255,255,0.5)");} else {$musicPlay.removeClass("music_play2");// 让文字不高亮$item.find("div").css("color", "rgba(255,255,255,0.5)");}// 3.4 切换序号的状态$item.find(".list_number").toggleClass("list_number2");$item.siblings().find(".list_number").removeClass("list_number2");
});
.content_list .list_number2 {color: transparent !important;background: url("../images/wave.gif") no-repeat 0 0;
}

播放工具类封装

(function (window) {function Player() {return new Player.prototype.init();}Player.prototype = {constructor: Player,init: function () {},};Player.prototype.init.prototype = Player.prototype;window.Player = Player;
})(window);
  1. 封装一个类,返回原型上的init()方法

    也就是通过init()创建类

  2. 定义这个类的原型

    将构造函数指向Player,并定义init方法

  3. Player原型上的init方法的原型指向Player的原型

  4. 将这个对象开放给window

音乐的播放暂停

  1. 在HTML页面插入一个audio标签,用于播放音乐

  2. 引入player工具库

  3. 实例化一个Player对象,并且传入audio对象

  4. 当按钮被点击时,调用播放音乐的方法

  5. 实现播放/暂停音乐的方法

    1. 当创建音乐标签时,在标签中保存索引及音乐信息

      // 定义一个方法创建一条音乐
      function createMusicItem(index, music) {var $item = $(...);$item.get(0).index = index;$item.get(0).music = music;return $item;
      }
      
    2. 接收两个参数,分别为indexmusic信息

    3. 定义一个遍历,用于记录当前索引

    4. 判断是否为同一首音乐

    Player.prototype = {currentIndex: -1,playMusic: function (index, music) {// 判断是否是同一首音乐if (this.currentIndex == index) {// 同一首音乐if (this.audio.paused) {this.audio.play();} else {this.audio.pause();}} else {//   不是同一首音乐this.$audio.attr("src", music.link_url);this.audio.play();this.currentIndex = index;}},
    };
    

底部播放/暂停/上一首/下一首

底部播放暂停的逻辑:

  1. 播放暂停

    • 从未播放过

      播放第一首

    • 播放过

      继续播放

    $musicPlay.click(function () {// 判断有没有播放过音乐if (player.currentIndex == -1) {// 没有播放过$(".list_music").eq(0).find(".list_menu_play").trigger("click");} else {// 已经播放过$(".list_music").eq(player.currentIndex).find(".list_menu_play").trigger("click");}
    });
    
  2. 上一首/下一首

    • 第一首

      上一首为最后一首

    • 最后一首

      下一首为第一首

    // 5 监听底部控制区域上一首按钮的点击
    $(".music_pre").click(function () {$(".list_music").eq(player.preIndex()).find(".list_menu_play").trigger("click");
    });
    // 6 监听底部控制区域下一首按钮的点击
    $(".music_next").click(function () {$(".list_music").eq(player.nextIndex()).find(".list_menu_play").trigger("click");
    });
    

    对象的preIndexnextIndex方法用于处理索引。

    preIndex: function () {var index = this.currentIndex - 1;if (index < 0) {index = this.musicList.length - 1;}return index;
    },nextIndex: function () {var index = this.currentIndex + 1;if (index > this.musicList.length - 1) {index = 0;}return index;},
    

删除歌曲

删除数据时需要注意的就是前台删除数据后,后台也无需保存数据。并且需要对标签保存的数据进行重新排序

// 7. 监听删除按钮的点击
$(".content_list").delegate(".list_menu_del", "click", function () {// 找到被点击的音乐var $item = $(this).parents(".list_music");// 判断当前删除的是否是正在播放的if ($item.get(0).index == player.currentIndex) {$(".music_next").trigger("click");}$item.remove();player.changeMusic($item.get(0).index);// 重新排序$(".list_music").each(function (index, ele) {ele.index = index;$(ele).find(".list_number").text(index + 1);});
});

删除后需要注意删除的数据是否是正在播放的音乐的前边,如果是需要将索引-1。否则会出现下一曲跳歌的现象。

changeMusic: function (index) {// 删除对应的数据this.musicList.splice(index, 1);//判断当前删除的是否是正在播放的前面的音乐if (index < this.currentIndex) {this.currentIndex = this.currentIndex - 1;}
},

切换歌曲信息

更换歌曲信息涉及到的基本信息包括:

  1. 右侧信息栏

    • 图片
    • 歌手
    • 歌曲名
    • 专辑名
  2. 底部控制条的名称、时间

实现这个这个功能也很简单,只是一些元素的替换。调用位置有两处

  1. 第一次获取歌曲时(成功)的回调

    初始化列表的第一个音乐

  2. 当点击其他歌曲时

// 2. 初始化歌曲信息
function initMusicInfo(music) {// 获取对应的元素var $musicImage = $(".song_info_pic img");var $musicName = $(".song_info_name a");var $musicSinger = $(".song_info_singer a");var $musicAblum = $(".song_info_ablum a");var $musicProgressName = $(".music_progress_name");var $musicProgressTime = $(".music_progress_time");var $musicBg = $(".mask_bg");// 给获取的到的元素赋值$musicImage.attr("src", music.cover);$musicName.text(music.name);$musicSinger.text(music.singer);$musicAblum.text(music.album);$musicProgressName.text(music.name + "/" + music.singer);$musicProgressTime.text("00:00 / " + music.time);$musicBg.css("background", 'url("' + music.cover + '")');
}
$.ajax({success: function (data) {initMusicInfo(data[0]);},
});
$(".content_list").delegate(".list_menu_play", "click", function () {// 3.6 切换歌曲信息initMusicInfo($item.get(0).music);
});

进度条的实现

  1. 获取被点击位置距离窗口的位置
  2. 获取默认距离窗口的位置
  3. 被点击的位置减去默认距离窗口的位置
  4. 点击进度条时,调整小圆点以及前景色的位置
progressClick: function () {var $this = this; //this 是progress// 监听背景的点击this.$progressBar.click(function (event) {//   获取背景距离窗口默认的位置var normalLeft = $(this).offset().left;//   获取点击的位置距离窗口默认的位置var eventLeft = event.pageX;//   设置前景的宽度$this.$progressLine.css("width", eventLeft - normalLeft);$this.$progressDot.css("left", eventLeft - normalLeft);});
},

进度条的拖动

  1. 鼠标拖拽使用mousemove方法监听,但必须在鼠标按下后监听
  2. 实现逻辑与点击一致
  3. 鼠标抬起则释放mousemove事件即可
progressMove: function () {var $this = this;// 1. 监听的鼠标的按下事件this.$progressBar.mousedown(function () {//   获取背景距离窗口默认的位置var normalLeft = $(this).offset().left;// 2. 监听鼠标的移动事件$(document).mousemove(function () {//   获取点击的位置距离窗口默认的位置var eventLeft = event.pageX;//   设置前景的宽度$this.$progressLine.css("width", eventLeft - normalLeft);$this.$progressDot.css("left", eventLeft - normalLeft);});});// 3. 监听鼠标的抬起事件$(document).mouseup(function () {$(document).off("mousemove");});
},

音乐时间、进度条同步

音乐时间同步

通过timeupdate事件监听是否播放,正在播放时,会不断触发这个事件。在事件内部通过durationcurrentTime获取当前时长和总时长。

于是可以在player类中新增加方法

musicTimeUpdate: function (callBack) {var $this = this;this.$audio.on("timeupdate", function () {var duration = $this.audio.duration;var currentTime = $this.audio.currentTime;var timeStr = $this.formatDate(currentTime, duration);callBack(currentTime, duration, timeStr);});
},// 格式化时间formatDate: function (currentTime, duration) {// 结束时间var endMin = parseInt(duration / 60);var endSec = parseInt(duration % 60);if (endMin < 10) {endMin = "0" + endMin;}if (endSec < 10) {endSec = "0" + endSec;}// 开始时间var startMin = parseInt(currentTime / 60);var startSec = parseInt(currentTime % 60);if (startMin < 10) {startMin = "0" + startMin;}if (startSec < 10) {startSec = "0" + startSec;}return startMin + ":" + startSec + " / " + endMin + ":" + endSec;},

在我们的index.js中只需要调用这个方法即可。

// 8. 监听播放的进度
player.musicTimeUpdate(function (currentTime, duration, timeStr) {// 同步时间$(".music_progress_time").text(timeStr);
});

进度条同步

同样的为进度条新增方法setProgress

setProgress: function (value) {if (value < 0 || value > 100) return;this.$progressLine.css({width: value + "%",});this.$progressDot.css({left: value + "%",});
},

这样完成后,在主函数中计算出当前时间所占比例即可调用此方法进行设置。

// 8. 监听播放的进度
player.musicTimeUpdate(function (currentTime, duration, timeStr) {// 同步进度条// 计算播放比例var value = (currentTime / duration) * 100;progress.setProgress(value);
});

因为使用了百分比进行修改元素,那么css的定位方式也需要修改一下:

.music_progress_info .music_progress_bar {position: relative;
}
.music_progress_bar .music_progress_dot {position: absolute;
}

点击进度条与歌曲同步

实现思路:

  1. 计算出总时长除以已播放时长的比例
  2. 将歌曲进度设置为歌曲时长乘以上一步的比例
progress.progressClick(function (value) {player.musicSeekTo(value);
});
progress.progressMove(function (value) {player.musicSeekTo(value);
});
musicSeekTo: function (value) {this.audio.currentTime = this.audio.duration * value;
},

为了实现拖拽时声音能够继续播放,因此将设置的方法改到mouseup事件中

progressMove: function (callBack) {var $this = this;var normalLeft, eventLeft;// 1. 监听的鼠标的按下事件this.$progressBar.mousedown(function () {//   获取背景距离窗口默认的位置normalLeft = $(this).offset().left;$this.isMove = true;// 2. 监听鼠标的移动事件$(document).mousemove(function () {//   获取点击的位置距离窗口默认的位置eventLeft = event.pageX;//   设置前景的宽度$this.$progressLine.css("width", eventLeft - normalLeft);$this.$progressDot.css("left", eventLeft - normalLeft);});});// 3. 监听鼠标的抬起事件$(document).mouseup(function () {$(document).off("mousemove");$this.isMove = false;// 计算进度条的比例var value = (eventLeft - normalLeft) / $this.$progressBar.width();callBack(value);});
},

声音控制

声音控制与进度条控制几乎一致

var $voiceBar = $(".music_voice_bar");
var $voiceLine = $(".music_voice_line");
var $voiceDot = $(".music_voice_dot");
voicePregress = Progress($voiceBar, $voiceLine, $voiceDot);
voicePregress.progressClick(function (value) {player.musicVoiceSeekTo(value);
});
voicePregress.progressMove(function (value) {player.musicVoiceSeekTo(value);
});
}

接下来为player类新增方法即可。

musicVoiceSeekTo: function (value) {// 取值0~1this.audio.volume = value;
},

bug修复

  1. 音乐进度的跳转应为一个正常的数字

    musicSeekTo: function (value) {if (isNaN(value)) return;this.audio.currentTime = this.audio.duration * value;
    },
    
  2. 音量同理且音量范围为0~1

    musicVoiceSeekTo: function (value) {if (isNaN(value)) return;if (value < 0 || value > 1) return;// 取值0~1this.audio.volume = value;
    },
    
  3. 拖拽超出范围

    progressMove: function (callBack) {var barWidth = this.$progressBar.width();// 1. 监听的鼠标的按下事件this.$progressBar.mousedown(function () {$(document).mousemove(function () {var offset = eventLeft - normalLeft;if (offset >= 0 && offset <= barWidth) {//   设置前景的宽度$this.$progressLine.css("width", eventLeft - normalLeft);$this.$progressDot.css("left", eventLeft - normalLeft);}});});
    

歌词设置

歌词解析并且加载(创建)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e8ojtcjv-1592652391977)(https://cdn.jsdelivr.net/gh/blogimg/HexoStaticFile2@latest/2020/06/20/c9ff8d630d1f80dbefae6f39268e5300.png)]

解析创建一个新的类用于解析歌词。

(function (window) {function Lyric(path) {return new Lyric.prototype.init(path);}Lyric.prototype = {constructor: Lyric,init: function (path) {this.path = path;},// 保存匹配的时间times: [],// 保存匹配的歌词lyrics: [],loadLyric: function (callBack) {var $this = this;$.ajax({url: $this.path,dataType: "text",success: function (data) {$this.pareLyric(data);callBack();},error: function (e) {},});},// 解析歌词的方法pareLyric: function (data) {var $this = this;var array = data.split("\n");// 正则表达式匹配内容var timeReg = /\[(\d*:\d*\.\d*)\]/;// 遍历取出每一条歌词$.each(array, function (index, ele) {//   处理歌词var lrc = ele.split("]")[1];//   排除空字符串(没有歌词)if (lrc.length == 1) return true;$this.lyrics.push(lrc);var res = timeReg.exec(ele);if (res == null) return true;var timeStr = res[1];var res2 = timeStr.split(":");var min = parseInt(res2[0]) * 60;var sec = parseFloat(res2[1]);var time = parseFloat(Number(min + sec).toFixed(2));$this.times.push(time);});console.log($this.times);console.log($this.lyrics);},};Lyric.prototype.init.prototype = Lyric.prototype;window.Lyric = Lyric;
})(window);

接下来只需要在自己的JavaScript中初始化这个类并且调用方法即可。

// 3. 初始化歌词信息
function initMusicLyric(music) {var lyric = new Lyric(music.link_lrc);var $lryicContainer = $(".song_lyric");lyric.loadLyric(function () {// 创建歌词列表$.each(lyric.lyrics, function (index, ele) {var $item = $("<li>" + ele + "</li>");$lryicContainer.append($item);});});
}

创建好了之后,还需要对样式进行一点点小的修改

.content_right .song_lyric {height: 150px;overflow: hidden;
}

歌词同步

歌词同步需要在监听播放的进度中去设置

// 8. 监听播放的进度
player.musicTimeUpdate(function (currentTime, duration, timeStr) {// 实现歌词的同步var index = lyric.currentIndex(currentTime);var $item = $(".song_lyric li").eq(index);$item.addClass("cur");$item.siblings().removeClass("cur");if (index <= 2) return;$(".song_lyric").css({marginTop: (-index + 2) * 30,});
});

因为使用了margin-top滚动歌词,那么需要将html也该动。

<div class="song_lyric_container"><ul class="song_lyric"></ul>
</div>

为了实现切换歌曲时,歌词也可以切换,也需要在切换歌曲时将保存的歌曲信息也切换。

loadLyric: function (callBack) {$this.times = [];$this.lyrics = [];
},
function initMusicLyric(music) {$lryicContainer.html("");
}
$(".content_list").delegate(".list_menu_play", "click", function () {// 3.7切换歌词信息initMusicLyric($item.get(0).music);
});

八、jQuery的QQ音乐播放器相关推荐

  1. 基于jQuery仿QQ音乐播放器网页版代码

    基于jQuery仿QQ音乐播放器网页版代码是一款黑色样式风格的网页QQ音乐播放器样式代码.效果图如下: 在线预览    源码下载 实现的代码. html代码: <div class=" ...

  2. jQuery仿QQ音乐播放器

    本文通过Html+CSS+jQuery开发仿QQ版的音乐播放器,是前端技术的综合应用,所用素材来源于网络,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点 在本例中用到的知识点如下,按jQuer ...

  3. 用jQuery实现qq音乐播放器

    折腾了很久,最终还是决定先放弃,继续学习jQuery后面的内容,做了有一大半吧,核心功能不想搞了,以后有时间再继续吧 贴代码: html: <!DOCTYPE html> <html ...

  4. 从零玩转jQuery之项目开发(QQ音乐播放器)

    QQ音乐播放器项目 大体效果如下: HTML结构分析: 一.页面布局 1.首先来看下HTML大体结构: <div class="header"></div> ...

  5. QQ音乐播放器-jQuery实现

    QQ音乐播放器 案例展示 案例实现的功能 静态页面的布局 歌曲信息的动态显示 鼠标悬停,功能按钮和文字高亮 歌曲信息的动态显示 歌曲播放 进度条显示和动态移动 纯净模式的模板设置和歌词写入 案例布局 ...

  6. mplayer-php,jQuery MPlayer网站音乐播放器插件

    jQuery MPlayer网站音乐播放器插件 这是一款2017年贺新春版的红色喜庆音乐播放器代码,jQuery MPlayer网站音乐播放器插件下载. 注意:演示效果在左下角收起来了,别以为没演示! ...

  7. jQuery练习_QQ音乐播放器

    jQuery练习_QQ音乐播放器 项目介绍 比较实用的音乐播放器,美观且便捷,值得做一做. 项目展示 项目分享 转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达.可以 ...

  8. QQ音乐播放器部分笔记

    QQ音乐播放器案例 1. 基本结构分析 三个部分: 头部区域 中间内容区 左边歌曲列表信息 上边按钮工具条和下边的滑动列表[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img- ...

  9. html5卡拉OK音乐播放器,QQ音乐播放器怎么打开卡拉OK模式

    QQ音乐播放器怎么打开卡拉OK模式 时间:2020-08-05 12:25:56 责任编辑:随便就行 QQ音乐播放器怎么打开卡拉OK模式?QQ音乐播放器是生活中常用的音乐播放器,很多人在使用QQ音乐播 ...

最新文章

  1. 张亚勤、韦乐平等综述论文:通信人工智能的下一个十年
  2. android view clip,Android 自定义View Clip
  3. 安卓 camera 调用流程_[Camera]Camera1 open、preview、take picture流程分析(3)
  4. Java Web学习(一)Web基础
  5. java索引ref_java – 如何使用jgit库将git HEAD指向特定的ref?
  6. is_file()和file_exists()
  7. 仪表指针样式_PPT标准图表太丑?试试仪表盘图表!
  8. 创新案例分享 | 一体化政务服务平台运维项目,全力提升平台服务效能
  9. python 金融风控模型_Python金融大数据风控建模实战 基于机器学习
  10. uniapp 公众号微信支付提示 调用支付jsapi缺少参数appid
  11. Linux查看开机自动运行的服务
  12. 展望2020:游戏本地化
  13. Soul源码总结-01-21
  14. json对象转换为json字符串
  15. 酒店管理系统(C语言)
  16. 多线程:模仿火车站售票
  17. 基于SPSS的K均值算法
  18. VMware虚拟机没有卸载干净无法重装的问题解决之道
  19. STM32F407+Cubemx学习应用[4]——DMA收发ModbusRS485数据——RS485温度传感器
  20. 基于单片机的毕业设计推荐

热门文章

  1. Mybatis——类型处理器TypeHandler
  2. 【深度域自适应】一、DANN与梯度反转层(GRL)详解
  3. Core Techniques And Algorithms In Game Programming
  4. JDBC连接mysql遇到的问题
  5. P21图像边缘发现(锐化):二阶导
  6. input元素及属性
  7. C#|Winform编程之(列表视图控件)listView控件
  8. 评委打分表模板_系高中英语作文模板——邀请信
  9. The MegaFace Benchmark-1 Million Faces for Recognition at Scale
  10. docker基础——Docker是什么