Lily_music 网页音乐播放器 -可搜索(附歌词联动播放效果解说)
博客地址:https://ainyi.com/59
写在前面
这是我今年(2018)年初的小项目,当时也是手贱,不想用别的播放器,想着做一个自己的网页播放器,有个歌曲列表、可关键词搜索、歌词滚动播放的效果,于是乎,就做了这一个 Lily_music
当时的感慨
有好几天没有发表博客了,这也是因为一直开发音乐和完善我的博客项目,好不容易抽出时间总结一下这几天所做的东西,还这么多课,实则匆忙
今天难得逃了一次课,就趁这时间,该写写就写写吧~~
进入正题: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 异步请求到歌词文件内容,然后就可以进行字符串裁剪,单单取出时间和歌词,html5 播放器可以获取到当前播放时间,就可以实现当前播放时间和当前歌词一一对应,附上代码:
loadLrc :function(){//加载歌词
var vallrc = $(".hidetextlrc").text();
//如果没有上传歌词或者删除了歌词
if(!vallrc || $(".is_deleteLrc").text() == 1){
$(".lrc_content_notext").text("暂无歌词");
$(".lrc_content_notext").show();
return;
}
var isHrefLrc = $(".is_href_lrc").text();
//如果是上传的歌词,那就要拼接上服务器地址
if(isHrefLrc == 0) vallrc = basePath + "/" + vallrc;
$.ajax({ //异步请求获取本地歌词
url:vallrc,
type:"post",
success:function(data){
//第一次分离歌词
var lrcArr = data.split("[");
//存放分离后的歌词
var html = "";
var lrclast = null; //记录上一行的歌词
var lrcmes = null; //记录当前行的歌词
var bofo = -1; //记录上一行歌词的秒数
var ms = -1; //当前这一行的秒数
for(var i = 0;i < lrcArr.length;i++){
//第二次分割歌词,变成["03:01.08","这个世界变得更加美丽"],数组以逗号分隔
var arr = lrcArr[i].split("]");
//取到数组arr下标为1的歌词部分
//将上一行的歌词赋值给lrclast
lrclast = lrcmes;
//得到当前歌词
lrcmes = arr[1];
//取到时间
var time = arr[0].split("."); //变成["03:01","08"]
//取到time下标为0的分钟和秒
var ctime = time[0].split(":"); //变成["03","01"];
//将上一行的秒数赋值给bofo
bofo = ms;
//转化成秒数
ms = ctime[0]*60 + ctime[1]*1;
//如果上一行和当前行秒数相同,则当前行秒数++ ,解决秒数相同的办法
if(bofo == ms){
ms++;
} else if (ms >= 0){
if(!isNaN(bofo)){ // 如果是数字
var classeName = "l_"+bofo;
var concon = bofo; // bofo会自增,所以下面for循环条件用这个变量来代替
for(var j = 0;j < ms-concon-1;j++){
classeName += " l_"+ ++bofo;
}
if(ms>=0 && lrclast != null){
html += "<li class='"+classeName+"'>"+lrclast+"</li>";
}
}
}
}
//装载最后一行歌词的机制,先获取歌曲总时间
setTimeout(function(){
var allall = krAudio.audioDom.duration;
var classlaName = "l_"+ms;
var conben = ms; //ms会自增,所以下面for循环条件必须用这个变量来代替
for(var j = 0;j < allall-conben-1;j++){
classlaName += " l_"+ ++ms;
}
html += "<li class='"+classlaName+"'>"+lrcmes+"</li>";
//把解析好的歌词放入歌词展示区中
$("#lrcly").html(html);
$("#lyrics").html(html);
},200);
}
});
// 联动音乐播放歌词
krAudio.audioDom.addEventListener("timeupdate",function(){
//获取当前播放时间,获得的是秒数
var time = this.currentTime;
//解析音乐对应的时间
var m = parseInt(time / 60);//获取此时的分钟
var s = parseInt(time); //转换int类型,获取此时的秒数
$(".l_"+s).addClass("lrcsel").siblings().removeClass("lrcsel");
//歌词滚动条,使歌词在中间的计算公式:
//第n行歌词*li的高度-歌词区域中间的li(就是包括这个li,取这个li的一半)以上的li的总高度
//局部歌词的控制
$(".lrc_content_box").stop().animate({
scrollTop:(($(".lrcsel").index()+1)*29 - 145)//减去偏差,使当前歌词在中间
},240);
//全屏歌词的控制
$("#lyrics").stop().animate({
scrollTop:(($(".lrcsel").index()+1)*24 - 168)//减去偏差,使当前歌词在中间
},240);
});
},
这种歌词解析、联动播放的实现是我之前乐诗博客采用的一种方案,感觉也不错
重点来了
此次采用的是另一种歌词解析方式,利用 js 正则表达式全部替换的方式
替换方式
var reg = /-/g; // g表示全部替换 ,要替换的字符串是-
createTime = createTime.replace(reg,"/"); // 第二个参数表示替换成 /
// 替换成2018/04/03
歌词解析
//解析歌词
function parseLyric(lrc) {
var lyrics = lrc.split("\n");
var lrcText = {};
for(var i=0;i<lyrics.length;i++){
var lyric = decodeURIComponent(lyrics[i]);
var timeReg = /\[\d*:\d*((\.|\:)\d*)*\]/g;
var timeRegExpArr = lyric.match(timeReg);
if(!timeRegExpArr)continue;
var clause = lyric.replace(timeReg,'');
for(var k = 0,h = timeRegExpArr.length;k < h;k++) {
var t = timeRegExpArr[k];
var min = Number(String(t.match(/\[\d*/i)).slice(1)),
sec = Number(String(t.match(/\:\d*/i)).slice(1));
var time = min * 60 + sec;
lrcText[time] = clause;
}
}
return lrcText;
}
这样子解析出来的是一个对象,存放着键值对
键:时间(秒)
值:歌词
就可以直接做一个 for in 循环将每句歌词添加到歌词区域,将时间添加到每句歌词的样式控制 class 名
根据每句歌词的时间,就可以在播放器的 timeupdate 监听事件里实现滚动播放歌词了(代码上面有)
拖动进度条
鼠标拖动进度条的时候,有三个监听事件
按下:onmousedown
移动:onmousemove
弹起:onmouseup
这里鼠标移动事件需要放在鼠标按下事件里面,当鼠标弹起时,在里面清除移动、弹起两个事件,以免弹起时还执行鼠标按下拖动事件(也可以定义一把锁来控制)
还有很多细节点的问题,上一曲下一曲临界值、搜索后的播放控制、列表小菜单与主按钮之间的联动、三种播放模式(顺序播放、随机播放、单曲循环)等等等等... 有坑也有欢笑
截图展示
项目链接
在线演示:Lily_music
GitHub:https://github.com/Krryxa/Lily_music
欢迎 start
博客地址:https://ainyi.com/59
Lily_music 网页音乐播放器 -可搜索(附歌词联动播放效果解说)的更多相关文章
- 自制 h5 音乐播放器 可搜索
闲言碎语: 有好几天没有发表博客了,这也是因为一直开发音乐和完善我的博客项目,好不容易抽出时间总结一下这几天所做的东西,笔试又不断通知,实则匆忙 今天难得逃了一次课,就趁这时间,该写写就写写吧~~ 进 ...
- C#winfrom播放器动态加载歌词
上周我们进行了结业项目答辩,是播放器项目.有一个关于播放器变唱歌边加载歌词的方法特别有意思,像酷狗那样子歌词和歌曲同步滚播的样子. 这里的工具是Visual Studio 2013,使用语言是C#和. ...
- 仿迅雷播放器教程 -- 基于VLC的MFC播放器 (6)
代码下载:http://download.csdn.net/detail/qq316293804/6409417 昨天的教程里写着预计MFC播放器会隔得久一点,但是今晚仔细看了下VLC的常 ...
- vlc播放器设置开机自动全屏播放网络视频流
因工作需要,要用vlc视频播放器实现开机自动全屏播放某个网络视频流.百度了下,说的都很模糊,经过整理,设置方法如下: 一,添加视频流地址:rtsp://wowzaec2demo.streamlock. ...
- 仿迅雷播放器教程 -- 基于ffmpeg的C++播放器 (1)
2011年12月份的时候发了这篇博客 http://blog.csdn.net/qq316293804/article/details/7107049 ,博文最后说会开源一个播放器,没想到快两年了,才 ...
- 仿迅雷播放器教程 -- 基于VLC的C++播放器 (4)
经过前面的介绍,想必大家对VLC和ffmpeg都有一定印象了,还记得学习ffmpeg多么蛋疼吗?那么VLC会不会也这么蛋疼呢? 那么我们来看一段官方的Demo,Alberl精简了Demo,只留 ...
- 开源播放器 ijkplayer (一) :使用Ijkplayer播放直播视频
1.ijkplayer 编码 IjkPlayer支持硬解码和软解码. 软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_R ...
- JavaScript多个h5播放器video,点击一个播放其他暂停
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 前端视频插件Aliplayer播放器简单使用(基于地址播放)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
随机推荐
- LeetCode 单链表专题 (一)
目录 LeetCode 单链表专题 <c++> \([2]\) Add Two Numbers \([92]\) Reverse Linked List II \([86]\) Parti ...
- 微信小程序中的AJAX——POST,GET区别
注意:发送服务器时的DATA 最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String .转换规则如下: 对于 GET 方法的数据,会将数 ...
- Go语言基础之包
Go语言基础之包 在工程化的Go语言开发项目中,Go语言的源码复用是建立在包(package)基础之上的.本文介绍了Go语言中如何定义包.如何导出包的内容及如何导入其他包. Go语言的包(packag ...
- C. Neko does Maths
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 818C.soft thief
Yet another round on DecoForces is coming! Grandpa Maks wanted to participate in it but someone has ...
- iptables安装
1.安装iptable iptable-service #先检查是否安装了iptables service iptables status #安装iptables yum install -y ipt ...
- 接口调试之Postman 使用方法详解
一.Postman背景介绍 用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具.今天给大家介 ...
- 【安富莱二代示波器教程】第16章 附件A---电阻屏触摸校准
第16章 附件A---电阻屏触摸校准 二代示波器的触摸校准比较简单,随时随地都可以做触摸校准,按下K1按键即可校准.有时候我们做触摸校准界面,需要在特定的界面才可以进入触摸校准状态,非常繁琐 ...
- SDL 开发实战(五): SDL 纹理渲染
本文我们讲一下如何使用SDL_Texture将视频纹理渲染出来. 1. SDL 视频渲染相关对象 SDL 视频渲染主要涉及到四个对象:SDL_Window.SDL_Render.SDL_Texture ...
- Android studio的错误:radle sync failed: Cause: failed to find target android-21 :
这个错误在Android studio中经常出现,特别是你在编译不同的app的时候,到底是什么原因会导致该错误产生呢? 首先看错误信息,是找不到目标android版本-21导致的,这就很明显了,你的目 ...