jQuery仿QQ音乐播放器
程序员文章站
2022-08-09 17:12:03
本文通过Html+CSS+jQuery开发仿QQ版的音乐播放器,是前端技术的综合应用,所用素材来源于网络,仅供学习分享使用,如有不足之处,还请指正。 ......
本文通过html+css+jquery开发仿qq版的音乐播放器,是前端技术的综合应用,所用素材来源于网络,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
在本例中用到的知识点如下,按jquery和css进行区分:
jquery 是一个 javascript 库, 极大地简化了 javascript 编程,常见知识点如下:
- 通过标签获取jquery对象:var $audio =$("audio");
- 通过选择符获取jquery对象并设置文本内容:$(".music_progrss_time").text(timestr);
- 通过选择符,标签名获取对象并获取第i个子元素:$(".song_lyric ul li").eq(index);
- 通过ajax异步获取数据并刷新页面:$.ajax({});
- 通过类选择符获取元素并进行隐藏或显示:$(this).find(".list_menu").stop().fadein(100);
- 通过委托动态设置单击事件,主要针对动态生成元素:$(".content_list").delegate(".list_check", "click", function() {});
- 通过addclass添加类,removeclass删除类,toggleclass切换类,hasclass是否包含类
- 获取与对象同级的兄弟节点:$musiclist.siblings();
- 触发相关事件:$(".music_next").trigger("click");
css通过使用 css 我们可以大大提升网页开发的工作效率!本例使用知识点如下:
- 设置距离左边的距离:margin-left: 20px; 设置距离右边的距离:margin-right: 20px;
- 设置透明度:opacity: 0.6; 值[0,1]从透明到全不透明
- 设置背景图片:background: url(../img/player_logo.png) no-repeat 0 0;设置背景颜色和透明度:background: rgba(255,255,255,0.5);
- 设置li的样式:list-style: none;
- 设置显示样式为行内块:display: inline-block;
- 设置圆角:border-radius: 5px;
- 设置相对位置:position: relative;
- 背景图片的起始坐标:background-position: 0 -75px;
示例效果图及结构划分
本例的示例效果图及结构划分如下所示:
html核心代码
header部分代码:主要用于显示logo和登录显示,如下所示:
1 <div class="header"> 2 <h1 class="logo"> 3 <a href="#"></a> --by alan.hsiang 4 </h1> 5 <ul class="register"> 6 <li>登录</li> 7 <li>设置</li> 8 </ul> 9 </div>
中间区域部分:主要包括坐边的列表和右边的歌曲相关,如下所示:
1 <div class="content"> 2 <div class="content_in"> 3 <div class="content_left"> 4 <div class="content_toolbar"> 5 <span><i></i>收藏</span> 6 <span><i></i>添加到</span> 7 <span><i></i>下载</span> 8 <span><i></i>删除</span> 9 <span><i></i>清空列表</span> 10 </div> 11 <div class="content_list"> 12 <ul> 13 <li class="list_title"> 14 <div class="list_check"><i></i></div> 15 <div class="list_number"></div> 16 <div class="list_name">歌曲</div> 17 <div class="list_singer">歌手</div> 18 <div class="list_time">时长</div> 19 </li> 20 </ul> 21 </div> 22 </div> 23 <div class="content_right"> 24 <div class="song_info"> 25 <a href="javascript:;" class="song_info_pic"> 26 <img src="" alt="" /> 27 </a> 28 <div class="song_info_name">歌曲名称:<a href="javascript:;" class=""></a></div> 30 <div class="song_info_singer">歌手名:<a href="javascript:;" class=""></a></div> 32 <div class="song_info_album">专辑名称:<a href="javascript:;" class=""></a></div> 34 </div> 35 <div class="song_lyric"><ul></ul></div> 37 </div> 38 </div> 39 </div> 40
底部区域代码,主要用于播放相关内容,如下所示:
1 <div class="footer"> 2 <div class="footer_in"> 3 <a href="javascript:;" class="music_pre" title="上一首"></a> 4 <a href="javascript:;" class="music_play" title="播放"></a> 5 <a href="javascript:;" class="music_next" title="下一首"></a> 6 <div class="music_progress_info"> 7 <div class="music_progress_top"> 8 <span class="music_progrss_name"></span> 9 <span class="music_progrss_time"></span> 10 </div> 11 <div class="music_progress_bar"> 12 <div class="music_progress_line"> 13 <div class="music_progress_dot"></div> 16 </div> 17 </div> 18 </div> 19 <a href="javascript:;" class="music_mode" title="播放模式"></a> 20 <a href="javascript:;" class="music_fav" title="收藏"></a> 21 <a href="javascript:;" class="music_down" title="下载"></a> 22 <a href="javascript:;" class="music_comment" title="评论"></a> 23 <a href="javascript:;" class="music_only" title="纯净模式"></a> 24 <div class="music_voice"> 25 <a href="javascript:;" class="music_voice_info" title="声音"></a> 26 <div class="music_voice_bar"> 27 <div class="music_voice_line"> 28 <div class="music_voice_dot"></div> 29 </div> 30 </div> 31 </div> 32 </div> 33 </div> 34
jquery功能性核心代码
在本示例中,从功能上区分,主要分为播放模块,进度条模块,歌词模块,各个模块相互独立,所以进行了适当的封装。
播放模块【play】主要包括歌曲的初始化,播放与暂停,上一首,下一首,播放同步,跳转等功能,核心代码如下:
1 (function(window){ 2 function player($audio){ 3 return new player.prototype.init($audio); 4 } 5 player.prototype={ 6 constructor :player, 7 musiclist:[], 8 currindex:-1, 9 $audio:null, 10 audio:null, 11 init:function($audio){ 12 this.$audio=$audio;//jquey包装对象 13 this.audio=$audio.get(0);//原生audio对象 14 }, 15 play:function(index,music){ 16 console.log(index,music); 17 console.log(this.$audio); 18 if(this.currindex==index){ 19 //同一首音乐,则是暂停,播放之间切换 20 21 if(this.audio.paused){ 22 this.audio.play(); 23 }else{ 24 this.audio.pause(); 25 } 26 }else{ 27 //不是同一首,重新播放 28 this.$audio.attr('src',music.link_url); 29 this.audio.play(); 30 this.currindex=index; 31 } 32 }, 33 preindex:function(){ 34 var index=this.currindex-1; 35 if(index<0){ 36 index=this.musiclist.length-1; 37 } 38 return index; 39 }, 40 nextindex:function(){ 41 var index=this.currindex+1; 42 if(index>this.musiclist.length-1){ 43 index=0; 44 } 45 return index; 46 }, 47 del:function(index){ 48 this.musiclist.splice(index,1); 49 if(index<this.currindex){ 50 this.currindex=this.currindex-1; 51 } 52 }, 53 musictimeupdate:function(callback){ 54 //需要一个回调函数作为参数 55 var that=this; 56 //监听audio播放事件 57 this.$audio.on("timeupdate",function(){ 58 var duration=that.audio.duration; 59 var currenttime=that.audio.currenttime; 60 var timestr=that.formattime(currenttime,duration); 61 //参数是一个回调函数 62 callback(duration,currenttime,timestr); 63 }); 64 }, 65 //定义一个格式化时间的方法 66 formattime:function (currenttime,duration){ 67 //总时长 68 var endmin=parseint(duration/60); 69 var endsec=parseint(duration%60); 70 endmin=endmin<10?"0"+endmin:endmin; 71 endsec=endsec<10?"0"+endsec:endsec; 72 //当前时长 73 var curmin=parseint(currenttime/60); 74 var cursec=parseint(currenttime%60); 75 curmin=curmin<10?"0"+curmin:curmin; 76 cursec=cursec<10?"0"+cursec:cursec; 77 return curmin+":"+cursec+" / "+endmin+":"+endsec; 78 }, 79 musicseekto:function(value){ 80 var that=this; 81 var duration=that.audio.duration; 82 if(isnan(duration))return; 83 if(isnan(value))return; 84 that.audio.currenttime=duration*value ; 85 }, 86 musicvoiceseekto:function(value){ 87 if(isnan(value))return; 88 if(value<=0 || value>=1) return; 89 this.audio.volume=value; 90 } 91 }; 92 player.prototype.init.prototype=player.prototype; 93 window.player=player; 94 })(window);
歌词模块【lyric】,主要包括歌词的加载,解析,同步等功能,核心代码如下:
1 (function(window){ 2 function lyric(path){ 3 return new lyric.prototype.init(path); 4 } 5 lyric.prototype={ 6 constructor :lyric, 7 times:[], 8 lyrics:[], 9 index:-1, 10 init:function(path){ 11 this.path=path; 12 }, 13 loadlyric:function(callback){ 14 var that=this; 15 $.ajax({ 16 type: "get", 17 datatype:"text", 18 contenttype: "application/text; charset=utf-8", 19 url: that.path, 20 success: function(data) { 21 //console.log(data); 22 that.parselyric(data); 23 callback(); 24 }, 25 error: function(e) { 26 console.log(e); 27 } 28 }); 29 }, 30 parselyric:function(data){ 31 var that=this; 32 //初始化歌词和时间 33 that.times=[]; 34 that.lyrics=[]; 35 that.index=-1; 36 // 37 var array=data.split("\n"); 38 //console.log(array); 39 var timereg=/\[(\d*:\d*\.\d*)\]/; 40 $.each(array, function(index,ele) { 41 //console.log(ele); 42 // 43 var lyc=ele.split("]")[1]; 44 if(lyc==null || lyc.length==1){ 45 return true;//排除空字符串 46 } 47 that.lyrics.push(lyc); 48 49 var res=timereg.exec(ele); 50 //console.log(res); 51 if(res==null){ 52 return true; //排除空时间 53 } 54 var timestr=res[1]; 55 var res2=timestr.split(":"); 56 var min=parseint(res2[0]) *60; 57 var sec=parsefloat(res2[1]) ; 58 var res3=parsefloat( number(min+sec).tofixed(2)); 59 //console.log(res3); 60 that.times.push(res3); 61 }); 62 console.log(that.times.length +" , "+ that.lyrics.length); 63 }, 64 currentlyric:function(currenttime){ 65 //console.log(currenttime); 66 if(currenttime>this.times[0]){ 67 this.index++; 68 this.times.shift();//删除第一个元素,并返回剩余的数组 69 } 70 return this.index; 71 } 72 }; 73 lyric.prototype.init.prototype=lyric.prototype; 74 window.lyric=lyric; 75 })(window);
进度条模块【progress】主要包括:进度条的初始化,单击,拖动,回调等功能,核心代码如下:
1 (function(window){ 2 function progress($progressbar,$progressline,$progressdot){ 3 return new progress.prototype.init($progressbar,$progressline,$progressdot); 4 } 5 progress.prototype={ 6 constructor :progress, 7 ismove:false, 8 init:function($progressbar,$progressline,$progressdot){ 9 this.$progressbar=$progressbar; 10 this.$progressline=$progressline; 11 this.$progressdot=$progressdot; 12 }, 13 progressclick:function(callback){ 14 //console.log(this.$progressbar); 15 var that=this;//此时的this表示progress 16 this.$progressbar.click(function(event){ 17 //此时的this表示progrssbar点击的对象 18 var normalleft = $(this).offset().left;//控件默认距左边的位置 19 var eventleft = event.pagex;//当前鼠标点击的距左边的位置 20 that.$progressline.css("width",eventleft-normalleft); 21 that.$progressdot.css("left",eventleft-normalleft); 22 //计算进度条的比例 23 var value=(eventleft-normalleft)/$(this).width(); 24 callback(value); 25 }); 26 }, 27 progressmove:function(callback){ 28 var that=this;//此时的this表示progress 29 var normalleft =-1; 30 var eventleft=-1; 31 var barwidth=this.$progressbar.width(); 32 this.$progressbar.mousedown(function(){ 33 that.ismove=true; 34 normalleft = $(this).offset().left;//控件默认距左边的位置 35 36 $(document).mousemove(function(){ 37 //此时的this表示progrssbar点击的对象 38 eventleft = event.pagex;//当前鼠标点击的距左边的位置 39 var v=eventleft-normalleft; 40 if(v>=0 && v<=barwidth){ 41 //判断值的有效范围再赋值 42 that.$progressline.css("width",eventleft-normalleft); 43 that.$progressdot.css("left",eventleft-normalleft); 44 } 45 }); 46 }); 47 $(document).mouseup(function(){ 48 $(document).off("mousemove"); 49 that.ismove=false; 50 //计算进度条的比例 51 var value=(eventleft-normalleft)/that.$progressbar.width(); 52 //鼠标抬起时触发,防止音乐断断续续 53 callback(value); 54 }); 55 }, 56 setprogress:function(value){ 57 if(this.ismove)return; 58 if(value<0 || value>100){ 59 return; 60 } 61 this.$progressline.css("width",value+"%"); 62 this.$progressdot.css("left",value+"%"); 63 } 64 }; 65 progress.prototype.init.prototype=progress.prototype; 66 window.progress=progress; 67 })(window);
加载流程,包括初始化歌曲列表,歌词信息,注册事件,初始化进度条等功能,本例中的歌曲列表和歌词信息,均是通过ajax从本地文件中获取,核心代码如下:
1 $(function() { 2 var $audio =$("audio"); 3 var player=new player($audio); 4 var progress=null; 5 var voiceprogress=null; 6 var lyric=null; 7 //1.加载音乐 8 getplayerlist(); 9 //2.注册事件 10 initevent(); 11 //3.初始化进度条,包括声音 12 initprogress(); 13 14 //音乐播放同步 15 player.musictimeupdate(function(duration,currenttime,timestr){ 16 //同步时间 17 $(".music_progrss_time").text(timestr); 18 //同步进度条 19 var value=currenttime/duration *100; 20 progress.setprogress(value); 21 //实现歌词同步 22 var oldindex=lyric.index; 23 var index=lyric.currentlyric(currenttime); 24 if(oldindex==index)return; 25 var item=$(".song_lyric ul li").eq(index); 26 item.addclass("cur"); 27 item.siblings().removeclass("cur"); 28 if(index<0) return; 29 $(".song_lyric ul").css({ 30 margintop:(-index+2)*40 31 }); 32 }) 33 34 //获取列表函数 35 function getplayerlist() { 36 $.ajax({ 37 type: "get", 38 url: "music_list.json", 39 success: function(data) { 40 //player.musiclist=data; 41 //console.log(data); 42 var musiclist = $(".content_list ul"); 43 $.each(data, function(index, ele) { 44 var item = createmusicitem(index, ele); 45 musiclist.append(item); 46 }); 47 //默认初始化第一首歌曲信息 48 initmusicinfo(data[0]); 49 50 //初始化歌词信息 51 initmusiclyric(data[0]); 52 }, 53 error: function(e) { 54 console.log(e); 55 } 56 }); 57 } 58 //定义一个方法,创建一条音乐 59 function createmusicitem(index, music) { 60 var $item = $("<li class=\"list_music\">\n" + 61 "<div class=\"list_check\">\n" + 62 "<i></i>\n" + 63 "</div>\n" + 64 "<div class=\"list_number\">\n" + 65 (index + 1) + 66 "</div>\n" + 67 "<div class=\"list_name\">\n" + 68 music.name + 69 "<div class=\"list_menu\">\n" + 70 "<a href=\"javascript:;\" title=\"播放\" class=\"list_menu_play\"></a>\n" + 71 "<a href=\"javascript:\;\" title=\"添加\"></a>\n" + 72 "<a href=\"javascript:;\" title=\"下载\"></a>\n" + 73 "<a href=\"javascript:;\" title=\"分享\"></a>\n" + 74 "</div>\n" + 75 "</div>\n" + 76 "<div class=\"list_singer\">\n" + 77 music.singer + 78 "</div>\n" + 79 "<div class=\"list_time\">\n" + 80 "<span>\n" + 81 music.time + 82 "</span>\n" + 83 "<a href=\"javascript:;\" title=\"删除\" class=\"list_menu_del\"></a>\n" + 84 "</div>\n" + 85 "</li>"); 86 $item.get(0).index=index; 87 $item.get(0).music=music; 88 return $item; 89 } 90 91 //初始化音乐信息 92 function initmusicinfo(music){ 93 //获取元素 94 var $musicimg=$(".song_info_pic img"); 95 var $musicname=$(".song_info_name a"); 96 var $musicsinger=$(".song_info_singer a"); 97 var $musicalbum=$(".song_info_album a"); 98 var $musictopname=$(".music_progrss_name"); 99 var $musictoptime=$(".music_progrss_time"); 100 var $musicbg=$(".mask_bg"); 101 //赋值 102 $musicimg.attr("src",music.cover); 103 $musicname.text(music.name); 104 $musicsinger.text(music.singer); 105 $musicalbum.text(music.album); 106 $musictopname.text(music.name+" / "+ music.singer); 107 $musictoptime.text("00:00 / "+music.time); 108 $musicbg.css("background","url('"+music.cover+"') no-repeat 0 0;"); 109 110 } 111 112 //初始化歌词信息 113 function initmusiclyric(music){ 114 lyric=new lyric(music.link_lrc); 115 var lyriccontainer=$(".song_lyric ul"); 116 //清空信息 117 lyriccontainer.html(""); 118 //加载歌词 119 lyric.loadlyric(function(){ 120 //加载完成后处理函数 121 $.each(lyric.lyrics,function(index,ele){ 122 var item=$("<li>"+ele+"</li>"); 123 lyriccontainer.append(item); 124 }); 125 }); 126 } 127 //注册事件 128 function initevent() { 129 //监听歌曲的移入移出事件 130 //通过委托动态监听事件 131 $(".content_list").delegate(".list_music", "mouseover", function() { 132 //移入事件:1.显示子菜单 2. 隐藏时长 ,显示删除按钮 133 $(this).find(".list_menu").stop().fadein(100); 134 $(this).find(".list_time a").stop().fadein(100); 135 $(this).find(".list_time span").stop().fadeout(100); 136 // 137 $(this).find(".list_name").addclass("list_music_hover"); 138 }); 139 $(".content_list").delegate(".list_music", "mouseleave", function() { 140 //移出事件:1.隐藏子菜单 2. 显示时长 ,隐藏删除按钮 141 $(this).find(".list_menu").stop().fadeout(100); 142 $(this).find(".list_time a").stop().fadeout(100); 143 $(this).find(".list_time span").stop().fadein(100); 144 $(this).find(".list_name").removeclass("list_music_hover"); 145 }); 146 147 //以下绑定事件只针对静态语句 148 // $(".list_music").hover(function(){ 149 // //移入事件:1.显示子菜单 2. 隐藏时长 ,显示删除按钮 150 // $(this).find(".list_menu").stop().fadein(100); 151 // $(this).find(".list_time a").stop().fadein(100); 152 // $(this).find(".list_time span").stop().fadeout(100); 153 // },function(){ 154 // //移出事件:1.隐藏子菜单 2. 显示时长 ,隐藏删除按钮 155 // $(this).find(".list_menu").stop().fadeout(100); 156 // $(this).find(".list_time a").stop().fadeout(100); 157 // $(this).find(".list_time span").stop().fadein(100); 158 // }); 159 160 $(".content_list").delegate(".list_check", "click", function() { 161 $(this).toggleclass("list_checked"); 162 var musiclist = $(this).parents(".list_music"); 163 if($(this).hasclass("list_checked")) { 164 musiclist.find("div").css("color", "#fff"); 165 musiclist.siblings().find("div").css("color", "rgba(255,255,255,0.5)"); 166 } else { 167 musiclist.find("div").css("color", "rgba(255,255,255,0.5)"); 168 } 169 }); 170 // //监听复选框的点击事件 171 // $(".list_check").click(function(){ 172 // $(this).toggleclass("list_checked"); 173 // }); 174 175 //监听点击播放事件 176 $(".content_list").delegate(".list_menu_play", "click", function() { 177 //切换播放图标 178 $(this).toggleclass("list_menu_play2"); 179 //还原其他项的图标 180 var $musiclist = $(this).parents(".list_music"); 181 182 // console.log($musiclist.get(0).index); 183 // console.log($musiclist.get(0).music); 184 185 $musiclist.siblings().find(".list_menu_play").removeclass("list_menu_play2"); 186 //底部图标同步 187 if($(this).hasclass("list_menu_play2")) { 188 $(".music_play").addclass("music_pause"); 189 $musiclist.find("div").css("color", "#fff"); 190 $musiclist.siblings().find("div").css("color", "rgba(255,255,255,0.5)"); 191 } else { 192 $(".music_play").removeclass("music_pause"); 193 $musiclist.find("div").css("color", "rgba(255,255,255,0.5)"); 194 } 195 $musiclist.find(".list_number").toggleclass("list_number_play"); 196 $musiclist.siblings().find(".list_number").removeclass("list_number_play"); 197 //播放 198 player.play($musiclist.get(0).index,$musiclist.get(0).music); 199 // 200 initmusicinfo($musiclist.get(0).music); 201 //同步歌词 202 initmusiclyric($musiclist.get(0).music); 203 }); 204 205 //监听删除事件 206 $(".content_list").delegate(".list_menu_del", "click", function() { 207 var $item=$(this).parents(".list_music"); 208 $item.remove(); 209 player.del($item.get(0).index); 210 if($item.get(0).index==player.currindex){ 211 //如果删除的是当前播放的歌曲,则自动播放下一首 212 $(".music_next").trigger("click"); 213 } 214 //修改序号 215 $(".list_music").each(function(index,ele){ 216 ele.index=index; 217 $(ele).find(".list_number").text(index+1); 218 }); 219 }); 220 //监听底部按钮 221 //播放 222 $(".music_play").click(function(){ 223 //判断是否有播放过音乐 224 if(player.currindex==-1){ 225 //表示没有播放过 226 $(".list_music").eq(0).find(".list_menu_play").trigger("click"); 227 228 }else{ 229 //表示之前有播放过 230 $(".list_music").eq(player.currindex).find(".list_menu_play").trigger("click"); 231 } 232 }); 233 //前一首 234 $(".music_pre").click(function(){ 235 $(".list_music").eq(player.preindex()).find(".list_menu_play").trigger("click"); 236 }); 237 //下一首 238 $(".music_next").click(function(){ 239 $(".list_music").eq(player.nextindex()).find(".list_menu_play").trigger("click"); 240 }); 241 //声音事件 242 $(".music_voice_info").click(function(){ 243 //图标切换 244 $(this).toggleclass("music_voice_info2"); 245 if($(this).hasclass("music_voice_info2")){ 246 //无声音 247 player.musicvoiceseekto(0); 248 }else{ 249 //有声音 250 player.musicvoiceseekto(1); 251 } 252 }); 253 } 254 //初始化进度条 255 function initprogress(){ 256 //进度条 257 var $progressbar=$(".music_progress_bar"); 258 var $progressline=$(".music_progress_line"); 259 var $progressdot=$(".music_progress_dot"); 260 progress=new progress($progressbar,$progressline,$progressdot); 261 progress.progressclick(function(value){ 262 console.log("进度点0001"); 263 player.musicseekto(value); 264 }); 265 progress.progressmove(function(value){ 266 player.musicseekto(value); 267 }); 268 //声音条 269 var $musicvoicebar=$(".music_voice_bar"); 270 var $musicvoiceline=$(".music_voice_line"); 271 var $musicvoicedot=$(".music_voice_dot"); 272 voiceprogress=new progress($musicvoicebar,$musicvoiceline,$musicvoicedot); 273 voiceprogress.progressclick(function(value){ 274 console.log("声音点0001"); 275 player.musicvoiceseekto(value); 276 }); 277 voiceprogress.progressmove(function(value){ 278 player.musicvoiceseekto(value); 279 }); 280 } 281 282 });
备注
人活着,就是要做自己喜欢的事情。无忧,无虑,无怨,无悔。打造一款属于自己的音乐播放器,听歌也会别有一番风味。