本文通过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 });
备注
人活着,就是要做自己喜欢的事情。无忧,无虑,无怨,无悔。打造一款属于自己的音乐播放器,听歌也会别有一番风味。
来源:https://www.cnblogs.com/hsiang/p/12639967.html
