终于把这播放器做出来了。。。

**2014.07.10 更新
修复以下两项严重错误:

  1. add_lrc() 传参错误
  2. 没有深入了解 lrc 文件标准,感谢 http://www.zhixing123.cn/jsp/js-lrc.html 提供参考文章**

可以像 http://futa.ooo/1648.html 一样,用 playerid.add_lrc() 手动添加歌词,也可以用 add_lrc() 添加 lrc 格式歌词,更可以使用 get_lrc() 获取百度音乐的 lrc 歌词。。。

使用方法

1
get_lrc(name,singer,playerid);
1
add_lrc(lrc_data,playerid);

手动添加的。。。看前面链接的那篇文章吧

例子:http://lab.imjs.work/getlrc/test.html

附源码
test.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/>
<script src="get_lrc.js"></script>
<style>
/*
* Lyric support by kookxiang(http://ikk.me)
*/
.kk_player { width: 100%; max-height: 40px; }
.kk_lrc { height: 125px; overflow: auto; padding: 0; margin: 0; }
.kk_lrc li { display: block; text-align: center; color: gray; line-height: 20px; margin: 2px 0 3px 0; min-height: 20px; }
.kk_lrc .current { color: black; font-weight: bold; }
.kk_lrc, .kk_lrc * { -webkit-transition-duration: 1s; -moz-transition-duration: 1s; transition-duration: 1s; }
.kk_lrc ::selection { background: transparent; background: rgba(127, 127, 127, 0.1); }
.kk_lrc_box { position: relative; }
.kk_lrc_box:before { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 0; top: 0; pointer-events: none; }
.kk_lrc_box:after { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 100%; bottom: 0; pointer-events: none; }

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { -webkit-border-radius: 10px; border-radius: 10px; }
::-webkit-scrollbar-thumb { -webkit-border-radius: 10px; border-radius: 10px; background: rgba(96, 96, 96, 0.8); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); }
::-webkit-scrollbar-thumb:window-inactive { background: rgba(96, 96, 96, 0.4); }
</style>
</head>

<body>
<pre>get_lrc() 方法</pre>
<audio class="kk_player" controls="true" id="kk_lrc_hongdou" src="http://lab.imjs.work/getlrc/hongdou.mp3" preload="metadata">您的浏览器不支持HTML5的 audio 标签,无法为您播放!</audio><br />
<div class="kk_lrc_box"><ul id="kk_lrc_hongdou_lrc" class="kk_lrc">
<li></li><li></li><li></li>
</ul></div>
<script>
get_lrc('红豆','王菲','hongdou');
</script>
<pre>add_lrc() 方法</pre>
<audio class="kk_player" controls="true" id="kk_lrc_hongqingting" src="http://lab.imjs.work/getlrc/hongqingting.mp3" preload="metadata">您的浏览器不支持HTML5的 audio 标签,无法为您播放!</audio><br />
<div class="kk_lrc_box"><ul id="kk_lrc_hongqingting_lrc" class="kk_lrc">
<li></li><li></li><li></li>
</ul></div>
<script>
add_lrc("[ti:红蜻蜓]<br />[ar:小虎队]<br />[al:红蜻蜓]<br />[00:00.00]红蜻蜓<br />[00:04.84]词:长郑刚 曲:李子恒<br />[00:08.85]演唱:小虎队<br />[02:09.02][00:32.74]飞呀 飞呀<br />[02:10.22][00:33.82]看那红色蜻蜓飞在蓝色天空<br />[02:13.52][00:37.33]游戏在风中不断追逐他的梦<br />[02:17.90][00:41.59]天空是永恒的家 大地就是他的王国<br />[02:21.88][00:45.56]飞翔是生活<br />[02:26.18][00:49.96]我们的童年也像追逐成长吹来的风<br />[02:30.25][00:53.94]轻轻地吹着梦想 慢慢地升空<br />[02:34.64][00:58.24]红色的蜻蜓是我小时侯的小小英雄<br />[02:38.57][01:02.30]多希望有一天能和他一起飞<br />[02:42.92][01:06.57]当烦恼愈来愈多 玻璃弹珠愈来愈少<br />[02:46.85][01:10.62]我知道我已慢慢地长大了<br />[02:51.33][01:14.93]红色的蜻蜓曾几何时<br />[02:53.94][01:17.38]也在我岁月慢慢不见了<br />[03:33.66][02:59.98][01:23.59]我们都已经长大 好多梦正在飞<br />[03:41.68][03:08.18][01:31.83]就像童年看到地红色的蜻蜓<br />[03:50.09][03:16.59][01:40.38]我们都已经长大 好多梦还要飞<br />[03:58.47][03:24.83][01:48.52]就像现在心目中红色的蜻蜓<br />[04:05.06][01:55.12](music)<br />[04:34.64]End<br />[04:39.23]","hongqingting");
</script>
</body>
</html>

get_lrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
function get_lrc(name,singer,playerid) {
var script = document.createElement('script');
script.setAttribute('src', "http://lab.imjs.work/getlrc/?name="+encodeURIComponent(name)+"&singer="+encodeURIComponent(singer)+"&playerid="+encodeURIComponent(playerid)+"&callback=con_lrc");
//load javascript
document.getElementsByTagName('head')[0].appendChild(script);
return true;
}

function con_lrc(lrc_data,playerid) {
var err_msg={"-1":"服务器没有接收到完整数据","-2":"无法正常获取 xml 文件","-3":"找不到该曲目","-4":"未收录 lrc 歌词","-5":"无法正常获取 lrc 歌词"};
if (lrc_data.status=="error") {
console.error(err_msg[lrc_data.errcode]);
return false;
}
eval("var "+playerid+" = load_kk_lrc(\""+playerid+"\");");
for (i=0;i<lrc_data.result.length;i++) {
var lrcArray=lrc_data.result[i].split("<br />");
var timeKey=new Object();
var strArray=new Array();
for (var i = 0,l = lrcArray.length;i < l;i++) {
//正则匹配 删除[00:00.00]格式或者 [00:00:00]格式
//所有的 lrc 都应该 decode 一下,因为各种语言都可能有
clause = decodeURIComponent(lrcArray[i]).replace(/\[\d*?:\d*?[\.:]\d*?\]/g,'');
timeRegExpArr = decodeURIComponent(lrcArray[i]).match(/\[(\d*?):(\d*?)[\.:](\d*?)\]/g);
if (timeRegExpArr!=null) {
for (var k = 0,h = timeRegExpArr.length;k < h;k++) { //第一遍循环,JSON存储歌词,数组存储时间
_timeRegExpArr = timeRegExpArr[k].match(/^\[(\d*?):(\d*?)[\.:](\d*?)\]$/);
min = parseFloat(_timeRegExpArr[1]);
sec = parseFloat(_timeRegExpArr[2]);
msec = parseFloat(_timeRegExpArr[3]);
time=min * 60 + sec + msec/100;
if (!timeKey[time]) {
strArray.push(time);
timeKey[time] = clause + '<br />';
} else {
timeKey[time] += clause + '<br />';
}
}
}
}
strArray.sort(function(a,b) {
return a - b;
});
for (var i = 0,l = strArray.length;i < l;i++) { //第二遍循环,JSON存储时间,数组存储歌词
var tempIndex = strArray[i],
tempClause = timeKey[tempIndex];
console.log([tempIndex,tempClause]);
eval(playerid+".add_lrc(tempIndex,tempClause);");
}
}
eval(playerid+".init();");
return true;
}

function add_lrc(lrc_data,playerid) {
con_lrc({'status':'success','errcode':'0','result':[lrc_data.replace("\n","<br />")]},playerid);
return true;
}

/*
* Lyric support by kookxiang(http://ikk.me)
*/
function load_kk_lrc(playerid){
var kk_lrc = new Object();
kk_lrc.extra_top = 1;
kk_lrc.current = -1;
kk_lrc.current_obj;
kk_lrc.offset = 0;
kk_lrc.current_start = -1;
kk_lrc.next_update_time = -1;
kk_lrc.showtime = -1;
kk_lrc.lrc_offset = -1;
kk_lrc.lrc_height = -1;
kk_lrc.lrc = [];
kk_lrc.lrcobj = null;
kk_lrc.target = 0;
kk_lrc._target = 0;
kk_lrc.player_obj = document.getElementById('kk_lrc_' + playerid);
kk_lrc.lrc_obj = document.getElementById('kk_lrc_' + playerid + '_lrc');

kk_lrc.scroll_lrc = function () {
if(typeof kk_lrc.lrc[kk_lrc.current+2] != "undefined"){
for(id in kk_lrc.lrcobj) kk_lrc.lrcobj[id].className = '';
kk_lrc.lrcobj[kk_lrc.current+3].className = 'current';
}
kk_lrc.current_start = kk_lrc.lrc[kk_lrc.current];
kk_lrc.current++;
kk_lrc.current_obj = kk_lrc.lrcobj[kk_lrc.current+2];
kk_lrc.next_update_time = kk_lrc.lrc[kk_lrc.current];
kk_lrc.showtime = kk_lrc.next_update_time - kk_lrc.current_start;
kk_lrc.lrc_offset = kk_lrc.current_obj.offsetTop;
kk_lrc.lrc_height = kk_lrc.current_obj.offsetHeight;
};
kk_lrc.check_lrc_update = function () {
var curTime = kk_lrc.player_obj.currentTime;
if(curTime >= kk_lrc.next_update_time - 0.2){
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}
if(typeof kk_lrc.lrc[kk_lrc.current-1] != "undefined"){
kk_lrc.extra_top = (kk_lrc.next_update_time - curTime) / kk_lrc.showtime;
}
kk_lrc.target = Math.round(kk_lrc.lrc_offset - (125 - kk_lrc.lrc_height) / 2);
if(kk_lrc.target < 0) kk_lrc.target = 0;
};
kk_lrc.init = function () {
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.current = -1;
kk_lrc.lrcobj = kk_lrc.lrc_obj.getElementsByTagName('li');
kk_lrc.current_obj = kk_lrc.lrcobj[0];
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
kk_lrc.player_obj.addEventListener("seeked" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
kk_lrc.player_obj.addEventListener("durationchange" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
setInterval(function(){
if(kk_lrc.player_obj.paused) return;
if(kk_lrc.current_start > kk_lrc.player_obj.currentTime){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}else{
kk_lrc.check_lrc_update();
}
}, 100);
setInterval(function(){
if(kk_lrc._target == kk_lrc.target) return;
if(Math.abs(kk_lrc.lrc_obj.scrollTop - kk_lrc._target) > kk_lrc.lrc_height){
kk_lrc._target = kk_lrc.lrc_obj.scrollTop;
}
if(kk_lrc.player_obj.paused){
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.8 + kk_lrc.target * 0.2);
}else{
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.98 + kk_lrc.target * 0.02);
}
kk_lrc.lrc_obj.scrollTop = kk_lrc._target;
}, 5);
};
kk_lrc.add_lrc = function (time, lrc) {
kk_lrc.lrc.push(parseFloat(time) + kk_lrc.offset);
var lrc_line = document.createElement("li");
lrc_line.innerHTML = lrc;
kk_lrc.lrc_obj.appendChild(lrc_line);
};
kk_lrc.get_lrc = function (num) {
if(typeof kk_lrc.lrc[num] != "undefined"){
return kk_lrc.lrc[num][1];
}else{
return '';
}
}
kk_lrc.setoffset = function (num) {
kk_lrc.offset = num / 1000;
}
kk_lrc.fixFloat = function (num) {
return Math.ceil(num * 10) / 10;
}
return kk_lrc;
}

完整 Demo 下载:getlrc