前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自制 h5 音乐播放器 可搜索

自制 h5 音乐播放器 可搜索

作者头像
Krry
修改2019-04-22 14:49:32
4.2K0
修改2019-04-22 14:49:32
举报
文章被收录于专栏:KrryblogKrryblog

博客地址:https://ainyi.com/59

闲言碎语:

有好几天没有发表博客了,这也是因为一直开发音乐和完善我的博客项目,好不容易抽出时间总结一下这几天所做的东西,还这么多课,实则匆忙

今天难得逃了一次课,就趁这时间,该写写就写写吧~~

进入正题:Lily_music

本次开发,参照本人之前所做的 乐诗博客(文末会说到)的相关播放控制等功能,继续优化的结果。

前端模仿qq音乐界面,然后在此之上进行修改的界面,并使用了一点 es6 的语法

话说个人挺喜欢qq音乐界面的,简洁,当然也少不了背景模糊插件以及滚动条美化相关插件,

也用到了弹窗、点击复制歌曲链接和歌词链接相关功能,但是目前歌曲分享功能暂未实现、后续....

致谢:歌曲搜索参照某位大佬封装的 qq 音乐的 api,UI 界面参照另一位大神的一些解决方案,在此表示感谢

相关链接:

那么相关使用的开源插件有:

jQuery官方类库:https://jquery.com/

layer弹窗插件:http://layer.layui.com/

复制粘贴库插件:https://www.npmjs.com/package/clipboard-js

mCustomScrollbar滚动条美化插件:http://manos.malihu.gr/jquery-custom-content-scroller/

background-blur背景图片模糊特效插件:https://msurguy.github.io/background-blur/

还有播放、控制、歌词解析、搜索、加载动画sg类库等功能全部手写,爽的不行。

温馨提醒:

本播放器并不需要什么特别的运行环境,直接下载打开就能用了 ^_^

响应式优化,可在各种大小的设备运行打开

音乐搜索的结果均来自 qq音乐 (后续会继续扩大到多个平台)

本播放器还有一些 bug,需求就是不断满足的,虚心请教...

谈谈开发:

果断使用的是 H5 播放器,十分好用

一般在做这种播放器的开发,要多多使用面向对象的开发思想。

定义一个播放器对象,相关参数、方法如下:

播放器对象:krAudio

参数:

  播放器:audioDom

  进度条锁定:locked:true

  进度条按下的锁:kdown

  静音的锁:flag_volume

  当前音量:curentVoice

  当前播放的列表序号:Currentplay

  当前播放列表歌曲总数:allItem

  播放模式,1为列表循环:orderModes

方法:

  播放器初始化:init

  设置播放的音乐地址:seturl

  播放:play

  暂停:stop

  播放时间监听及处理:time

  时间格式化:format

  下一首:next

  上一首:prev

  播放模式:ordermode

  拖动进度条:controlTime

  拖动音量条:controlVoice

上面部分的参数及方法基本涵盖播放器该有的功能

歌词解析,我之前做的乐诗博客采用自己写的一种歌词解析滚动播放的方法:

首先明白一般歌词的形式是:[00:13.80]期望飞上恬静月球遥望每家的窗 [00:18.24]谁伴深爱细味露台玫瑰香

这样子的形式,利用 ajax 异步请求到歌词文件,然后就可以进行字符串裁剪,单单取出时间和歌词,一一对应

代码语言:javascript
复制
 1     loadLrc:function(){//加载歌词
 2         var vallrc = $(".hidetextlrc").text();
 3         //如果没有上传歌词或者删除了歌词
 4         if(!vallrc || $(".is_deleteLrc").text() == 1){
 5             $(".lrc_content_notext").text("暂无歌词");
 6             $(".lrc_content_notext").show();
 7             return;
 8         }
 9         var isHrefLrc = $(".is_href_lrc").text();
10         //如果是上传的歌词,那就要拼接上服务器地址
11         if(isHrefLrc == 0) vallrc = basePath + "/" + vallrc;
12         $.ajax({  //异步请求获取本地歌词
13             url:vallrc,
14             type:"post",
15             success:function(data){
16                 //第一次分离歌词
17                 var lrcArr = data.split("[");
18                 //存放分离后的歌词
19                 var html = "";
20                 var lrclast = null; //记录上一行的歌词
21                 var lrcmes = null; //记录当前行的歌词
22                 var bofo = -1; //记录上一行歌词的秒数
23                 var ms = -1; //当前这一行的秒数
24                 for(var i = 0;i < lrcArr.length;i++){
25                     //第二次分割歌词,变成["03:01.08","这个世界变得更加美丽"],数组以逗号分隔
26                     var arr = lrcArr[i].split("]");
27                     //取到数组arr下标为1的歌词部分
28                     //将上一行的歌词赋值给lrclast
29                     lrclast = lrcmes; 
30                     //得到当前歌词
31                     lrcmes = arr[1];
32                     //取到时间
33                     var time = arr[0].split("."); //变成["03:01","08"]
34                     //取到time下标为0的分钟和秒
35                     var ctime = time[0].split(":"); //变成["03","01"];
36                     //将上一行的秒数赋值给bofo
37                     bofo = ms;
38                     //转化成秒数
39                     ms = ctime[0]*60 + ctime[1]*1;
40                     //如果上一行和当前行秒数相同,则当前行秒数++ ,解决秒数相同的办法
41                     if(bofo == ms){
42                         ms++;
43                     }else if(ms >= 0){
44                         if(!isNaN(bofo)){ //如果是数字
45                             var classeName = "l_"+bofo;
46                             var concon = bofo;//bofo会自增,所以下面for循环条件用这个变量来代替
47                             for(var j = 0;j < ms-concon-1;j++){
48                                 classeName += " l_"+ ++bofo;
49                             }
50                             if(ms>=0 && lrclast != null){
51                                 html += "<li class='"+classeName+"'>"+lrclast+"</li>";
52                             }
53                         }
54                     }
55                 }
56                 //装载最后一行歌词的机制,先获取歌曲总时间
57                 setTimeout(function(){
58                     var allall = krAudio.audioDom.duration;
59                     var classlaName = "l_"+ms;
60                     var conben = ms; //ms会自增,所以下面for循环条件必须用这个变量来代替
61                     for(var j = 0;j < allall-conben-1;j++){
62                         classlaName += " l_"+ ++ms;
63                     }
64                     html += "<li class='"+classlaName+"'>"+lrcmes+"</li>";
65                     //把解析好的歌词放入歌词展示区中
66                     $("#lrcly").html(html);
67                     $("#lyrics").html(html);
68                 },200);
69             }
70         });
71         // 联动音乐播放歌词
72         krAudio.audioDom.addEventListener("timeupdate",function(){
73             //获取当前播放时间,获得的是秒数
74             var time = this.currentTime;
75             //解析音乐对应的时间
76             var m = parseInt(time / 60);//获取此时的分钟
77             var s = parseInt(time); //转换int类型,获取此时的秒数
78             $(".l_"+s).addClass("lrcsel").siblings().removeClass("lrcsel");
79             //歌词滚动条,使歌词在中间的计算公式:
80             //第n行歌词*li的高度-歌词区域中间的li(就是包括这个li,取这个li的一半)以上的li的总高度
81             //局部歌词的控制
82             $(".lrc_content_box").stop().animate({
83                 scrollTop:(($(".lrcsel").index()+1)*29 - 145)//减去偏差,使当前歌词在中间
84             },240);
85             //全屏歌词的控制
86             $("#lyrics").stop().animate({
87                 scrollTop:(($(".lrcsel").index()+1)*24 - 168)//减去偏差,使当前歌词在中间
88             },240);
89         });
90     },

这种歌词解析、联动播放的进度进行滚动是我之前乐诗博客采用的一种方案,感觉也不错

此次采用另一种解析方式,利用 js 正则表达式全部替换的方式

替换方式:

代码语言:javascript
复制
1 var reg = /-/g;  // g表示全部替换 ,要替换的字符串是-
2 createTime = createTime.replace(reg,"/"); // 第二个参数表示替换成 /
3  //替换成2018/04/03

歌词解析:

代码语言:javascript
复制
 1 //解析歌词
 2 function parseLyric(lrc) {
 3     var lyrics = lrc.split("\n");
 4     var lrcText = {};
 5     for(var i=0;i<lyrics.length;i++){
 6         var lyric = decodeURIComponent(lyrics[i]);
 7         var timeReg = /\[\d*:\d*((\.|\:)\d*)*\]/g;
 8         var timeRegExpArr = lyric.match(timeReg);
 9         if(!timeRegExpArr)continue;
10         var clause = lyric.replace(timeReg,'');
11         for(var k = 0,h = timeRegExpArr.length;k < h;k++) {
12             var t = timeRegExpArr[k];
13             var min = Number(String(t.match(/\[\d*/i)).slice(1)),
14                 sec = Number(String(t.match(/\:\d*/i)).slice(1));
15             var time = min * 60 + sec;
16             lrcText[time] = clause;
17         }
18     }
19     return lrcText;
20 }

这样子解析出来的是一个对象,存放着键值对,键:时间(秒),值(歌词)

就可以直接做一个 for in 循环将每句歌词添加到歌词区域,将时间添加到每句歌词的样式控制class

根据每句歌词的时间,就可以在播放器的 timeupdate 监听事件里实现滚动播放歌词了

鼠标拖动进度条的时候,有三个监听事件,

按下:onmousedown 

移动:onmousemove 

弹起:onmouseup 

这里鼠标移动事件需要放在鼠标按下事件里面,当鼠标弹起时,在里面清除移动、弹起两个事件,以免弹起时还执行鼠标按下拖动事件(也可以定义一把锁来控制)

还有很多细节点的问题,上一曲下一曲临界值、搜索后的播放控制、列表小菜单与主按钮之间的联动、三种播放模式等等等等... 有坑也有欢笑

另外给大家提供一个判断非空的方法:

代码语言:javascript
复制
 1 //判断非空
 2 function isEmpty(val) {
 3     val = $.trim(val);
 4     if (val == null)
 5         return true;
 6     if (val == undefined || val == 'undefined')
 7         return true;
 8     if (val == "")
 9         return true;
10     if (val.length == 0)
11         return true;
12     if (!/[^(^\s*)|(\s*$)]/.test(val))
13         return true;
14     return false;
15 }

ES6 都出来了,那当然要好好使用,在字符串拼接的代码,均使用 es6 语法,十分好用

截图展示:

项目链接:

在线演示:https://www.ainyi.com/Lily_music/

git:https://github.com/Krryxa/Lily_music

博客地址:https://ainyi.com/59

版权所有,转载请注明出处

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 闲言碎语:
  • 进入正题:Lily_music
  • 相关链接:
  • 温馨提醒:
  • 谈谈开发:
  • 截图展示:
  • 项目链接:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档