JavaScript的歌词同步组件
用于歌词同步,整理一下放出来,核心脚本只负责处理lrc格式的歌词和呈现,并提供同步功能。
很久没发文,一直想写点东西,整理整理这阵子的心得,很多笔记都在整理中。
最近给公司编写的一个JS UI,用于歌词同步,整理一下放出来,
核心脚本只负责处理lrc格式的歌词和呈现,并提供同步功能。

外部呈现等均可以良好定制。
基本调用如下:
var lrc=new LRC({lyricTable:obj,lyricWrapper:obj,curRowClassName:'xx',lyric:'xxx',separator:'<BR>'});
if(lrc.IsLyricValid()) lrc.DoSync(60);
DoSync(t)用于同步,参数t为当前播放进度,从播放器获得。
IsLyricValid()返回歌词是否合法的LRC格式。
贴出代码,附件下载中包含2个定制示例。代码在FF下跑不了,因为音乐播放插件跑不了~
1

/**//*2
* @author: huangxu3
* @date: 2008-114
* @site: http://wsky.cnblogs.com5
* @descript: sync display the lyric 6
* @usage:7
* //import lrc.css8
* var lrc=new LRC({lyricTable:obj,lyricWrapper:obj,curRowClassName:'xx',lyric:'xxx',separator:'<BR>'});9
* if(lrc.IsLyricValid()) lrc.DoSync(60);10
*11
* @note: 内部变量前缀lrc_,普通变量i,ii,index,arg..12
*/13

14

LRC=function()
{this.initialize.apply(this,arguments);}15

LRC.prototype=
{16
arrLyricTime:[],17
arrLyric:[],//全局可用,必须执行初始化18

initialize:function(arg)
{19
//私有20
this.lyricTable=arg.lyricTable;//目标歌词table21
this.lyricWrapper=arg.lyricWrapper;//目标歌词容器div22
this.curRowClassName=arg.curRowClassName;//选择行css样式名23
this.separator=arg.separator;//歌词行分隔符 如:<BR>24
//执行初始化25
this.arrLyricTime=[];26
this.arrLyric=[];27
this.initArray(arg.lyric);28
this.arrLyricTime=this.sort(this.arrLyricTime);29
this.setLyricTable(this.arrLyric);30
},31

initArray:function(lyric)
{32
var lrc_re=new RegExp('\[[0-9:.]*\]','g');//g全局标志,获取所有匹配结果必须33
var lrc_arr=lyric.split(this.separator);34
var lrc_temp=0;35
var lrc_filter=0;//无效行过滤标记36

for(var i=0;i<lrc_arr.length;i++)
{37
var lrc_txt=lrc_arr[i].replace(/\[[\w\W]*\]/g,'').Trim();//add to lyric text array38

if(lrc_txt=='')
{39
lrc_filter++;40
continue;41
} 42
this.arrLyric[i-lrc_filter]=lrc_txt;43

while((lrc_result = lrc_re.exec(lrc_arr[i])) != null)
{44
var lrc_second=this.parseSecond(lrc_result.toString().replace(/\[|\]/g,''));45
if(!isNaN(lrc_second))46
this.arrLyricTime[lrc_temp++]=(i-lrc_filter)+'|'+lrc_second;//arrLyricTime格式为"行号|秒",如:1|50,2|6047
}48
}49
},50
/////////////////////////////////////////////////////////////////////////////////////////51
// 公开函数 52
// IsLyricValid()判断是否合法lrc歌词 53
// DoSync()定位歌词54
/////////////////////////////////////////////////////////////////////////////////////////55

IsLyricValid:function(arrLyricTime)
{56
return this.arrLyricTime.length>0;57
},58

DoSync:function(curPosition)
{59
var lrc_times=this.arrLyricTime;60

for(var i=0;i<lrc_times.length;i++)
{61
var lrc_arrPre=lrc_times[i].split('|');62
63
if(i==0&&curPosition<lrc_arrPre[1]) break;//防止抖动64
65

if(lrc_times[i+1]==undefined)
{66
this.setRow(lrc_arrPre[0]);67
break;68
}69
70
var lrc_arrNext=lrc_times[i+1].split('|');71

if(curPosition>=lrc_arrPre[1]&&curPosition<lrc_arrNext[1])
{72
this.setRow(lrc_arrPre[0]);73
break;74
}75
} 76
},77
/////////////////////////////////////////////////////////////////////////////////////////78
//以下为内部辅助函数79
/////////////////////////////////////////////////////////////////////////////////////////80

parseSecond:function(time)
{81

try
{82
var lrc_arr=time.split(':');//time格式为时间格式 00:0083
return parseInt(lrc_arr[0])*60+parseFloat(lrc_arr[1]);84

}catch(ex)
{85
return 0;86
}87
},88

setLyricTable:function(arrLyric)
{89
this.lyricWrapper.scrollTop=0;//滚动条置顶90
91

if(this.lyricTable.rows.length>0)
{ 92
this.clearTable(this.lyricTable);93
}94

for(var i=0;i<arrLyric.length;i++)
{95
var lrc_tr=this.lyricTable.insertRow();96
var lrc_cell=lrc_tr.insertCell(0);97
lrc_cell.innerHTML=arrLyric[i];98
}99
},100

clearTable:function(lyricTable)
{101
var lrc_rowNum=lyricTable.rows.length;102

for (var i=0;i<lrc_rowNum;i++)
{103
lyricTable.deleteRow(i);104
lrc_rowNum=lrc_rowNum-1;105
i=i-1;106
} 107
},108

setRow:function(index)
{109
this.setRowClass(index);110
this.setScroll(index);111
},112

setRowClass:function(index)
{113
var lrc_rows=this.lyricTable.rows;114

for(var i=0;i<lrc_rows.length;i++)
{115
lrc_rows[i].className='';//TODO:直接添加样式至元素,防止外部css干扰116
}117
lrc_rows[index].className=this.curRowClassName;118
},119

setScroll:function(index)
{120
this.lyricWrapper.scrollTop=this.lyricTable.rows[index].offsetTop-this.lyricWrapper.offsetHeight/3;121
},122

sort:function(arrLyricTime)
{123

for(var i=0;i<arrLyricTime.length-1;i++)
{124

for(var ii=i+1;ii<arrLyricTime.length;ii++)
{125
var lrc_cur=parseFloat(arrLyricTime[i].split('|')[1]);126
var lrc_next=parseFloat(arrLyricTime[ii].split('|')[1]);127

if(lrc_cur>lrc_next)
{128
var lrc_temp=arrLyricTime[i];129
arrLyricTime[i]=arrLyricTime[ii];130
arrLyricTime[ii]=lrc_temp;131
}132
}133
} 134
return arrLyricTime;135
}136
}137

138

139
/////////////////////////////////////////////////////////////140
//外部函数141
/////////////////////////////////////////////////////////////142
String.prototype.Trim = function()143


{ 144
return this.replace(/^\s*|\s*$/g,"");145
}146

浙公网安备 33010602011771号