以下是 jplayer歌词同步音乐播放器特效代码 的示例演示效果:
部分效果截图:
HTML代码(index.html):
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>jplayer实现歌词同步的JS音乐播放器效果</title>
<meta http-equiv="Cache-Control" content="no-cache">
<meta name="viewport" content="width=device-width; initial-scale=1.0; minimum-scale=1.0; maximum-scale=1.4">
<meta name="MobileOptimized" content="240">
<link href="css/blue.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.jplayer.js"></script>
<script type="text/javascript" src="js/lrc.js"></script>
<style type="text/css">
* {
margin: 0;
padding: 0;
outline:none;
}
ul, ol, dl {
list-style: none;
}
.music_box{margin:50px auto;width:422px;}
.content {width: 402px;height:200px;overflow:hidden;padding:10px;background:#ccc;}
#lrc_list{margin:10px auto;background:#ccc;}
#lrc_list li{font:normal 14px/2.1 'microsoft yahei';text-align:center;}
#lrc_list li.hover {color:red;font-weight:bold;}
</style>
<script>
//<![CDATA[
$(document).ready(function(){
$("#jquery_jplayer_1").jPlayer({
ready: function (event) {
$(this).jPlayer("setMedia", {
mp3:"yangcong.mp3" //mp3的播放地址
});
},
timeupdate: function(event) {
if(event.jPlayer.status.currentTime==0){
time = "";
}else {
time = event.jPlayer.status.currentTime;
}
},
play: function(event) {
//点击开始方法调用lrc。start歌词方法 返回时间time
$.lrc.start($('#lrc_content').val(), function() {
return time;
});
},
ended:function(event){
$("#lrc_list").removeAttr("style").html("<li>歌曲播放完毕!</li>");
},
swfPath: "/js", //存放jplayer.swf的决定路径
solution:"html, flash", //支持的页面
supplied: "mp3", //支持的音频的格式
wmode: "window"
});
});
//]]>
</script>
</head>
<body>
<textarea id="lrc_content" name="textfield" cols="70" rows="10" style="display:none;">
[00:03.00]洋葱
[00:06.00]演唱:平安
[00:09.00]
[00:11.38]如果你眼神能够为我片刻的降临
[00:21.23]如果你能听到心碎的声音
[00:28.88]盘底的洋葱像我永远是配角戏
[00:35.74]偷偷的看着你偷偷的隐藏着自己
[00:43.48]
[00:44.90]如果你愿意一层一层
[00:48.46]一层的剥开我的心
[00:52.66]你会发现你会讶异
[00:56.40]你是我最压抑最深处的秘密
[01:00.26]如果你愿意一层一层
[01:03.69]一层的剥开我的心
[01:07.76]你会鼻酸你会流泪
[01:11.60]只要你能听到我看到我的全心全意
[01:18.30]
[01:19.11]如果你愿意一层一层
[01:22.57]一层的剥开我的心
[01:26.66]你会发现你会讶异
[01:30.41]你是我最压抑最深处的秘密
[01:34.48]如果你愿意一层一层
[01:37.58]一层的剥开我的心
[01:41.51]你会鼻酸你会流泪
[01:45.15]只要你能听到我看到我的全心全意
[01:53.55]
[01:55.65]你会鼻酸你会流泪
[01:59.84]只要你能听到我看到我的全心全意
</textarea>
<div class="music_box">
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_container_1" class="jp-audio">
<div class="jp-type-single">
<div class="jp-gui jp-interface">
<ul class="jp-controls">
<li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
<li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
<li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
<li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
<li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
<li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-volume-bar">
<div class="jp-volume-bar-value"></div>
</div>
<div class="jp-time-holder">
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
<ul class="jp-toggles">
<li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
<li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
</ul>
</div>
</div>
<div class="jp-title">
<ul>
<li>欢迎聆听</li>
</ul>
</div>
<div class="jp-no-solution"> <span>Update Required</span> To play the media you will need to either update your browser to a recent version or update your <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash plugin</a>. </div>
</div>
</div>
<div class="content">
<ul id="lrc_list">
<li>点击开始播放……</li>
</ul>
</div>
</div>
</body>
</html>
JS代码(lrc.js):
(function($){
$.lrc ={
handle:null,/* 定时执行句柄 */
list:[],/* lrc歌词及时间轴数组 */
regex:/^[^\[]*((?:\s*\[\d+\:\d+(?:\.\d+)?\])+)([\s\S]*)$/,/* 提取歌词内容行 */
regex_time:/\[(\d+)\:((?:\d+)(?:\.\d+)?)\]/g,/* 提取歌词时间轴 */
regex_trim:/^\s+|\s+$/,/* 过滤两边空格 */
callback:null,/* 定时获取歌曲执行时间回调函数 */
interval:0.3,/* 定时刷新时间,单位:秒 */
format:'<li>{
html}
</li>',/* 模板 */
prefixid:'lrc',/* 容器ID */
hoverClass:'hover',/* 选中节点的className */
hoverTop:100,/* 当前歌词距离父节点的高度 */
duration:0,/* 歌曲回调函数设置的进度时间 */
__duration:-1,/* 当前歌曲进度时间 */
/* 歌词开始自动匹配 */
start:function(txt,callback){
if(typeof(txt) != 'string' || txt.length < 1 || typeof(callback) != 'function') return;
/* 停止前面执行的歌曲 */
this.stop();
this.callback = callback;
var item = null,item_time = null,html = '';
/* 分析歌词的时间轴和内容 */
txt = txt.split("\n");
for(var i = 0;
i < txt.length;
i++){
item = txt[i].replace(this.regex_trim,'');
if(item.length < 1 || !(item = this.regex.exec(item))) continue;
while(item_time = this.regex_time.exec(item[1])){
this.list.push([parseFloat(item_time[1])*60+parseFloat(item_time[2]),item[2]]);
}
this.regex_time.lastIndex = 0;
}
/* 有效歌词 */
if(this.list.length > 0){
/* 对时间轴排序 */
this.list.sort(function(a,b){
return a[0]-b[0];
}
);
if(this.list[0][0] >= 0.1) this.list.unshift([this.list[0][0]-0.1,'']);
this.list.push([this.list[this.list.length-1][0]+1,'']);
for(var i = 0;
i < this.list.length;
i++)html += this.format.replace(/\{
html\}
/gi,this.list[i][1]);
/* 赋值到指定容器 */
$('#'+this.prefixid+'_list').html(html).animate({
marginTop:0}
,100).show();
/* 隐藏没有歌词的层 */
$('#'+this.prefixid+'_nofound').hide();
/* 定时调用回调函数,监听歌曲进度 */
this.handle = setInterval('$.lrc.jump($.lrc.callback());
',this.interval*1000);
}
else{
/* 没有歌词 */
$('#'+this.prefixid+'_list').hide();
$('#'+this.prefixid+'_nofound').show();
}
}
,/* 跳到指定时间的歌词 */
jump:function(duration){
if(typeof(this.handle) != 'number' || typeof(duration) != 'number' || !$.isArray(this.list) || this.list.length < 1) return this.stop();
if(duration < 0) duration = 0;
if(this.__duration == duration) return;
duration += 0.2;
this.__duration = duration;
duration += this.interval;
var left = 0,right = this.list.length-1,last = rightpivot = Math.floor(right/2),tmpobj = null,tmp = 0,thisobj = this;
/* 二分查找 */
while(left <= pivot && pivot <= right){
if(this.list[pivot][0] <= duration && (pivot == right || duration < this.list[pivot+1][0])){
//if(pivot == right) this.stop();
break;
}
else if( this.list[pivot][0] > duration ){
/* left */
right = pivot;
}
else{
/* right */
left = pivot;
}
tmp = left + Math.floor((right - left)/2);
if(tmp == pivot) break;
pivot = tmp;
}
if(pivot == this.pivot) return;
this.pivot = pivot;
tmpobj = $('#'+this.prefixid+'_list').children().removeClass(this.hoverClass).eq(pivot).addClass(thisobj.hoverClass);
tmp = tmpobj.next().offset().top-tmpobj.parent().offset().top - this.hoverTop;
tmp = tmp > 0 ? tmp * -1:0;
this.animata(tmpobj.parent()[0]).animate({
marginTop:tmp + 'px'}
,this.interval*1000);
}
,/* 停止执行歌曲 */
stop:function(){
if(typeof(this.handle) == 'number') clearInterval(this.handle);
this.handle = this.callback = null;
this.__duration = -1;
this.regex_time.lastIndex = 0;
this.list = [];
}
,animata:function(elem){
var f = j = 0,callback,_this={
}
,tween = function(t,b,c,d){
return -c*(t/=d)*(t-2) + b;
}
_this.execution = function(key,val,t){
var s = (new Date()).getTime(),d = t || 500,b = parseInt(elem.style[key]) || 0,c = val-b;
(function(){
var t = (new Date()).getTime() - s;
if(t>d){
t=d;
elem.style[key] = tween(t,b,c,d) + 'px';
++f == j && callback && callback.apply(elem);
return true;
}
elem.style[key] = tween(t,b,c,d)+'px';
setTimeout(arguments.callee,10);
}
)();
}
_this.animate = function(sty,t,fn){
callback = fn;
for(var i in sty){
j++;
_this.execution(i,parseInt(sty[i]),t);
}
}
return _this;
}
}
;
}
)(jQuery);
CSS代码(blue.css):
div.jp-audio,div.jp-audio-stream,div.jp-video{/* Edit the font-size to counteract inherited font sizing. * Eg. 1.25em = 1 / 0.8em */
font-size:1.25em;/* 1.25em for testing in site pages */
/* No parent CSS that can effect the size in the demos ZIP */
font-family:Verdana,Arial,sans-serif;line-height:1.6;color:#666;border:1px solid #009be3;background-color:#eee;}
div.jp-audio{width:420px;}
div.jp-audio-stream{width:182px;}
div.jp-video-270p{width:480px;}
div.jp-video-360p{width:640px;}
div.jp-video-full{/* Rules for IE6 (full-screen) */
width:480px;height:270px;/* Rules for IE7 (full-screen) - Otherwise the relative container causes other page items that are not position:static (default) to appear over the video/gui. */
position:static !important;position:relative}
/* The z-index rule is defined in this manner to enable Popcorn plugins that add overlays to video area. EG. Subtitles. */
div.jp-video-full div div{z-index:1000;}
div.jp-video-full div.jp-jplayer{top:0;left:0;position:fixed !important;position:relative;/* Rules for IE6 (full-screen) */
overflow:hidden;}
div.jp-video-full div.jp-gui{position:fixed !important;position:static;/* Rules for IE6 (full-screen) */
top:0;left:0;width:100%;height:100%;z-index:1001;/* 1 layer above the others. */
}
div.jp-video-full div.jp-interface{position:absolute !important;position:relative;/* Rules for IE6 (full-screen) */
bottom:0;left:0;}
div.jp-interface{position:relative;background-color:#eee;width:100%;}
div.jp-audio div.jp-type-single div.jp-interface{height:80px;}
div.jp-audio div.jp-type-playlist div.jp-interface{height:80px;}
div.jp-audio-stream div.jp-type-single div.jp-interface{height:80px;}
div.jp-video div.jp-interface{border-top:1px solid #009be3;}
/* @group CONTROLS */
div.jp-controls-holder{clear:both;width:440px;margin:0 auto;position:relative;overflow:hidden;top:-8px;/* This negative value depends on the size of the text in jp-currentTime and jp-duration */
}
div.jp-interface ul.jp-controls{list-style-type:none;margin:0;padding:0;overflow:hidden;}
div.jp-audio ul.jp-controls{width:380px;padding:20px 20px 0 20px;}
div.jp-audio-stream ul.jp-controls{width:142px;padding:20px 20px 0 20px;}
div.jp-video div.jp-type-single ul.jp-controls{width:78px;margin-left:200px;}
div.jp-video div.jp-type-playlist ul.jp-controls{width:134px;margin-left:172px;}
div.jp-video ul.jp-controls,div.jp-interface ul.jp-controls li{display:inline;float:left;}
div.jp-interface ul.jp-controls a{display:block;overflow:hidden;text-indent:-9999px;}
a.jp-play,a.jp-pause{width:40px;height:40px;}
a.jp-play{background:url("jplayer.blue.monday.jpg") 0 0 no-repeat;}
a.jp-play:hover{background:url("jplayer.blue.monday.jpg") -41px 0 no-repeat;}
a.jp-pause{background:url("jplayer.blue.monday.jpg") 0 -42px no-repeat;display:none;}
a.jp-pause:hover{background:url("jplayer.blue.monday.jpg") -41px -42px no-repeat;}
a.jp-stop,a.jp-previous,a.jp-next{width:28px;height:28px;margin-top:6px;}
a.jp-stop{background:url("jplayer.blue.monday.jpg") 0 -83px no-repeat;margin-left:10px;}
a.jp-stop:hover{background:url("jplayer.blue.monday.jpg") -29px -83px no-repeat;}
a.jp-previous{background:url("jplayer.blue.monday.jpg") 0 -112px no-repeat;}
a.jp-previous:hover{background:url("jplayer.blue.monday.jpg") -29px -112px no-repeat;}
a.jp-next{background:url("jplayer.blue.monday.jpg") 0 -141px no-repeat;}
a.jp-next:hover{background:url("jplayer.blue.monday.jpg") -29px -141px no-repeat;}
/* @end */
/* @group progress bar */
div.jp-progress{overflow:hidden;background-color:#ddd;}
div.jp-audio div.jp-progress{position:absolute;top:32px;height:15px;}
div.jp-audio div.jp-type-single div.jp-progress{left:110px;width:186px;}
div.jp-audio div.jp-type-playlist div.jp-progress{left:166px;width:130px;}
div.jp-video div.jp-progress{top:0px;left:0px;width:100%;height:10px;}
div.jp-seek-bar{background:url("jplayer.blue.monday.jpg") 0 -202px repeat-x;width:0px;height:100%;cursor:pointer;}
div.jp-play-bar{background:url("jplayer.blue.monday.jpg") 0 -218px repeat-x;width:0px;height:100%;}
/* The seeking class is added/removed inside jPlayer */
div.jp-seeking-bg{background:url("jplayer.blue.monday.seeking.gif");}
/* @end */
/* @group volume controls */
a.jp-mute,a.jp-unmute,a.jp-volume-max{width:18px;height:15px;margin-top:12px;}
div.jp-audio div.jp-type-single a.jp-mute,div.jp-audio div.jp-type-single a.jp-unmute{margin-left:210px;}
div.jp-audio div.jp-type-playlist a.jp-mute,div.jp-audio div.jp-type-playlist a.jp-unmute{margin-left:154px;}
div.jp-audio-stream div.jp-type-single a.jp-mute,div.jp-audio-stream div.jp-type-single a.jp-unmute{margin-left:10px;}
div.jp-audio a.jp-volume-max,div.jp-audio-stream a.jp-volume-max{margin-left:56px;}
div.jp-video a.jp-mute,div.jp-video a.jp-unmute,div.jp-video a.jp-volume-max{position:absolute;top:12px;margin-top:0;}
div.jp-video a.jp-mute,div.jp-video a.jp-unmute{left:50px;}
div.jp-video a.jp-volume-max{left:134px;}
a.jp-mute{background:url("jplayer.blue.monday.jpg") 0 -170px no-repeat;}
a.jp-mute:hover{background:url("jplayer.blue.monday.jpg") -19px -170px no-repeat;}
a.jp-unmute{background:url("jplayer.blue.monday.jpg") -60px -170px no-repeat;display:none;}
a.jp-unmute:hover{background:url("jplayer.blue.monday.jpg") -79px -170px no-repeat;}
a.jp-volume-max{background:url("jplayer.blue.monday.jpg") 0 -186px no-repeat;}
a.jp-volume-max:hover{background:url("jplayer.blue.monday.jpg") -19px -186px no-repeat;}
div.jp-volume-bar{position:absolute;overflow:hidden;background:url("jplayer.blue.monday.jpg") 0 -250px repeat-x;width:46px;height:5px;cursor:pointer;}
div.jp-audio div.jp-volume-bar{top:37px;left:330px;}
div.jp-audio-stream div.jp-volume-bar{top:37px;left:92px;}
div.jp-video div.jp-volume-bar{top:17px;left:72px;}
div.jp-volume-bar-value{background:url("jplayer.blue.monday.jpg") 0 -256px repeat-x;width:0px;height:5px;}
/* @end */
/* @group current time and duration */
div.jp-audio div.jp-time-holder{position:absolute;top:50px;}
div.jp-audio div.jp-type-single div.jp-time-holder{left:110px;width:186px;}
div.jp-audio div.jp-type-playlist div.jp-time-holder{left:166px;width:130px;}
div.jp-current-time,div.jp-duration{width:60px;font-size:.64em;font-style:oblique;}
div.jp-current-time{float:left;display:inline;}
div.jp-duration{float:right;display:inline;text-align:right;}
div.jp-video div.jp-current-time{margin-left:20px;}
div.jp-video div.jp-duration{margin-right:20px;}
/* @end */
/* @group playlist */
div.jp-title{font-weight:bold;text-align:center;}
div.jp-title,div.jp-playlist{width:100%;background-color:#ABCDEF;border-top:1px solid #009be3;}
div.jp-type-single div.jp-title,div.jp-type-playlist div.jp-title,div.jp-type-single div.jp-playlist{border-top:none;}
div.jp-title ul,div.jp-playlist ul{list-style-type:none;margin:0;padding:0 20px;font-size:.72em;}
div.jp-title li{padding:5px 0;font-weight:bold;}
div.jp-playlist li{padding:5px 0 4px 20px;border-bottom:1px solid #eee;}
div.jp-playlist li div{display:inline;}
/* Note that the first-child (IE6) and last-child (IE6/7/8) selectors do not work on IE */
div.jp-type-playlist div.jp-playlist li:last-child{padding:5px 0 5px 20px;border-bottom:none;}
div.jp-type-playlist div.jp-playlist li.jp-playlist-current{list-style-type:square;list-style-position:inside;padding-left:7px;}
div.jp-type-playlist div.jp-playlist a{color:#333;text-decoration:none;}
div.jp-type-playlist div.jp-playlist a:hover{color:#0d88c1;}
div.jp-type-playlist div.jp-playlist a.jp-playlist-current{color:#0d88c1;}
div.jp-type-playlist div.jp-playlist a.jp-playlist-item-remove{float:right;display:inline;text-align:right;margin-right:10px;font-weight:bold;color:#666;}
div.jp-type-playlist div.jp-playlist a.jp-playlist-item-remove:hover{color:#0d88c1;}
div.jp-type-playlist div.jp-playlist span.jp-free-media{float:right;display:inline;text-align:right;margin-right:10px;}
div.jp-type-playlist div.jp-playlist span.jp-free-media a{color:#666;}
div.jp-type-playlist div.jp-playlist span.jp-free-media a:hover{color:#0d88c1;}
span.jp-artist{font-size:.8em;color:#666;}
/* @end */
div.jp-video-play{width:100%;overflow:hidden;/* Important for nested negative margins to work in modern browsers */
cursor:pointer;background-color:rgba(0,0,0,0);/* Makes IE9 work with the active area over the whole video area. IE6/7/8 only have the button as active area. */
}
div.jp-video-270p div.jp-video-play{margin-top:-270px;height:270px;}
div.jp-video-360p div.jp-video-play{margin-top:-360px;height:360px;}
div.jp-video-full div.jp-video-play{height:100%;}
a.jp-video-play-icon{position:relative;display:block;width:112px;height:100px;margin-left:-56px;margin-top:-50px;left:50%;top:50%;background:url("jplayer.blue.monday.video.play.png") 0 0 no-repeat;text-indent:-9999px;}
div.jp-video-play:hover a.jp-video-play-icon{background:url("jplayer.blue.monday.video.play.png") 0 -100px no-repeat;}
div.jp-jplayer audio,div.jp-jplayer{width:0px;height:0px;}
div.jp-jplayer{background-color:#000000;}
/* @group TOGGLES */
/* The audio toggles are nested inside jp-time-holder */
ul.jp-toggles{list-style-type:none;padding:0;margin:0 auto;overflow:hidden;}
div.jp-audio .jp-type-single ul.jp-toggles{width:25px;}
div.jp-audio .jp-type-playlist ul.jp-toggles{width:55px;margin:0;position:absolute;left:325px;top:50px;}
div.jp-video ul.jp-toggles{margin-top:10px;width:100px;}
ul.jp-toggles li{display:block;float:right;}
ul.jp-toggles li a{display:block;width:25px;height:18px;text-indent:-9999px;line-height:100%;/* need this for IE6 */
}
a.jp-full-screen{background:url("jplayer.blue.monday.jpg") 0 -310px no-repeat;margin-left:20px;}
a.jp-full-screen:hover{background:url("jplayer.blue.monday.jpg") -30px -310px no-repeat;}
a.jp-restore-screen{background:url("jplayer.blue.monday.jpg") -60px -310px no-repeat;margin-left:20px;}
a.jp-restore-screen:hover{background:url("jplayer.blue.monday.jpg") -90px -310px no-repeat;}
a.jp-repeat{background:url("jplayer.blue.monday.jpg") 0 -290px no-repeat;}
a.jp-repeat:hover{background:url("jplayer.blue.monday.jpg") -30px -290px no-repeat;}
a.jp-repeat-off{background:url("jplayer.blue.monday.jpg") -60px -290px no-repeat;}
a.jp-repeat-off:hover{background:url("jplayer.blue.monday.jpg") -90px -290px no-repeat;}
a.jp-shuffle{background:url("jplayer.blue.monday.jpg") 0 -270px no-repeat;margin-left:5px;}
a.jp-shuffle:hover{background:url("jplayer.blue.monday.jpg") -30px -270px no-repeat;}
a.jp-shuffle-off{background:url("jplayer.blue.monday.jpg") -60px -270px no-repeat;margin-left:5px;}
a.jp-shuffle-off:hover{background:url("jplayer.blue.monday.jpg") -90px -270px no-repeat;}
/* @end */
/* @group NO SOLUTION error feedback */
.jp-no-solution{padding:5px;font-size:.8em;background-color:#eee;border:2px solid #009be3;color:#000;display:none;}
.jp-no-solution a{color:#000;}
.jp-no-solution span{font-size:1em;display:block;text-align:center;font-weight:bold;}
/* @end */