Jplayer歌词同步显示插件(修正IOS兼容问题)

1、该插件是一个jQuery的编写的跟jplayer实现歌词同步的插件,最终效果如图:

20140822162843773

2、首先引入jplayer的相关的js库和样式文件。

  • <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8” />
  • <link href=“skin/pink.flag/jplayer.pink.flag.css” rel=“stylesheet” type=“text/css” />
  • <script type=“text/javascript” src=“js/jquery-1.8.2.min.js”></script>
  • <script type=“text/javascript” src=“js/jquery.jplayer.min.js”></script>
  • <script type=“text/javascript” src=“js/jquery.jplayer.lyric.js”></script>

 

3、把我修改的jquery的js文件贴出来,以备以后不能下载的朋友参考实现:

  1. *修改内容说明:在原有基础上,需要使用start方法才能加载歌词,改进之后,在加载jplayer之前调用,显示歌词
  2. */
  3. (function($){
  4.     $.lrc = {
  5.         handle: null, /* 定时执行句柄 */
  6.         list: [], /* lrc歌词及时间轴数组 */
  7.         regex: /^[^
    ]((?:\s\[\d+\d+(?:\.\d+)?

    )+)([\s\S]*)$/, /* 提取歌词内容行 */

  8.         regex_time: /
    (\d+)((?:\d+)(?:\.\d+)?)

    /g, /* 提取歌词时间轴 */

  9.         regex_trim: /^\s+|\s+$/, /* 过滤两边空格 */
  10.         callback: null, /* 定时获取歌曲执行时间回调函数 */
  11.         interval: 0.3, /* 定时刷新时间,单位:秒 */
  12.         format: ‘<li>{html}</li>‘, /* 模板 */
  13.         prefixid: ‘lrc’, /* 容器ID */
  14.         hoverClass: ‘hover’, /* 选中节点的className */
  15.         hoverTop: 100, /* 当前歌词距离父节点的高度 */
  16.         duration: 0, /* 歌曲回调函数设置的进度时间 */
  17.         __duration: -1, /* 当前歌曲进度时间 */
  18.         hasLrc:0,/**记录是否有歌词标记**/
  19.         //初始化歌词
  20.         init: function(txt){
  21.         if(typeof(txt) != ‘string’ || txt.length < 1) return;
  22.             /* 停止前面执行的歌曲 */
  23.             this.stop();
  24.             var item = nullitem_time = nullhtml = ;
  25.             /* 分析歌词的时间轴和内容 */
  26.             //先按行拆分歌词
  27.             txt = txt.split(“\n”);
  28.             //对拆分的每行进行提取时间和歌词内容
  29.             for(var i = 0; i < txt.length; i++) {
  30.                 //获取一行并去掉两端的空格 [00:11.38]如果你眼神能够为我片刻的降临
  31.                 item = txt[i].replace(this.regex_trim, ”);
  32.                 //然后取出歌词信息
  33.                 if(item.length < 1 || !(item = this.regex.exec(item))) continue;
  34.                 while(item_time = this.regex_time.exec(item[1])) {
  35.                     this.list.push([parseFloat(item_time[1])*60+parseFloat(item_time[2]), item[2]]);
  36.                 }
  37.                 this.regex_time.lastIndex = 0;
  38.             }
  39.             /* 有效歌词 */
  40.             if(this.list.length > 0) {
  41.                 this.hasLrc =1;
  42.                 /* 对时间轴排序 */
  43.                 this.list.sort(function(a,b){ return a[0]-b[0]; });
  44.                 if(this.list[0][0] >= 0.1) this.list.unshift([this.list[0][0]-0.1, ”]);
  45.                 this.list.push([this.list[this.list.length-1][0]+1, ”]);
  46.                 for(var i = 0; i < this.list.length; i++)
  47.                     html += this.format.replace(/\{html\}/gi, this.list[i][1]);
  48.                 /* 赋值到指定容器 */
  49.                 $(‘#’+this.prefixid+’_list’).html(html).animate({ marginTop: 0 }, 100).show();
  50.                 /* 隐藏没有歌词的层 */
  51.                 $(‘#’+this.prefixid+’_nofound’).hide();
  52.                 /* 定时调用回调函数,监听歌曲进度 */
  53.                 //this.handle = setInterval(‘$.lrc.jump($.lrc.callback());’, this.interval*1000);
  54.             }else{ /* 没有歌词 */
  55.                 this.hasLrc =0;
  56.                 $(‘#’+this.prefixid+’_list’).hide();
  57.                 $(‘#’+this.prefixid+’_nofound’).show();
  58.             }
  59.         },
  60.         /* 歌词开始自动匹配 跟时间轴对应 */
  61.         /**callback时间 jplayer的当前播放时间**/
  62.         start: function(callback) {
  63.             this.callback = callback;
  64.             /* 有歌词则跳转到歌词时间轴 */
  65.             if(this.hasLrc == 1) {
  66.                 this.handle = setInterval(‘$.lrc.jump($.lrc.callback());’, this.interval*1000);
  67.             }
  68.         },
  69.         /* 跳到指定时间的歌词 */
  70.         jump: function(duration) {
  71.             if(typeof(this.handle) != ‘number’ || typeof(duration) != ‘number’ || !$.isArray(this.list) || this.list.length < 1) return this.stop();
  72.             if(duration < 0duration = 0;
  73.             if(this.__duration == duration) return;
  74.             duration += 0.2;
  75.             this.__duration = duration;
  76.             duration += this.interval;
  77.             var left = 0right = this.list.length-1, last = right
  78.                 pivot = Math.floor(right/2),
  79.                 tmpobj = nulltmp = 0thisobj = this;
  80.             /* 二分查找 */
  81.             while(left <= pivot && pivot <= right) {
  82.                 if(this.list[pivot][0] <= duration && (pivot == right || duration < this.list[pivot+1][0])) {
  83.                     //if(pivot == right) this.stop();
  84.                     break;
  85.                 }else if( this.list[pivot][0] > duration ) { /* left */
  86.                     right = pivot;
  87.                 }else{ /* right */
  88.                     left = pivot;
  89.                 }
  90.                 tmp = left + Math.floor((right – left)/2);
  91.                 if(tmp == pivot) break;
  92.                 pivot = tmp;
  93.             }
  94.             if(pivot == this.pivot) return;
  95.             this.pivot = pivot;
  96.             tmpobj = $(‘#’+this.prefixid+’_list’).children().removeClass(this.hoverClass).eq(pivot).addClass(thisobj.hoverClass);
  97.             tmp = tmpobj.next().offset().top-tmpobj.parent().offset().top – this.hoverTop;
  98.             tmp = tmp > 0 ? tmp * -1 : 0;
  99.             this.animata(tmpobj.parent()[0]).animate({marginTop: tmp + ‘px’}, this.interval*1000);
  100.         },
  101.         /* 停止执行歌曲 */
  102.         stop: function() {
  103.             if(typeof(this.handle) == ‘number’) clearInterval(this.handle);
  104.             this.handle = this.callback = null;
  105.             this.__duration = -1;
  106.             this.regex_time.lastIndex = 0;
  107.             this.list = [];
  108.         },
  109.         animata: function(elem) {
  110.             var f = j = 0, callback, _this={},
  111.                 tween = function(t,b,c,d){ return -c*(t/=d)*(t-2) + b; }
  112.             _this.execution = function(key, val, t) {
  113.                 var s = (new Date()).getTime(), d = t || 500,
  114.                     b = parseInt(elem.style[key]) || 0,
  115.                     c = val-b;
  116.                 (function(){
  117.                     var t = (new Date()).getTime() – s;
  118.                     if(t>d){
  119.                         t=d;
  120.                         elem.style[key] = tween(t,b,c,d) + ‘px’;
  121.                         ++f == j && callback && callback.apply(elem);
  122.                         return true;
  123.                     }
  124.                     elem.style[key] = tween(t,b,c,d)+’px’;
  125.                     setTimeout(arguments.callee, 10);
  126.                 })();
  127.             }
  128.             _this.animate = function(sty, t, fn){
  129.                 callback = fn;
  130.                 for(var i in sty){
  131.                     j++;
  132.                     _this.execution(i,parseInt(sty[i]),t);
  133.                 }
  134.             }
  135.             return _this;
  136.         }
  137.     };
  138. })(jQuery);

4、在jplayer初始化中使用如下:

  1. //修改说明,修改了IOS10以上的兼容问题,歌词初始化不加载的问题。
  2. var u = navigator.userAgent;
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  3. $(document).ready(function(){
  4.     $(“#jquery_jplayer_1”).jPlayer({
  5.         ready: function () {
  6.             //初始化歌词信息(传入歌词文件文本)
  7.             $.lrc.init($(‘#lrc_content’).val());
  8.             $(this).jPlayer(“setMedia”, {
  9.                 title: “Bubble”,
  10.                 mp3: “mp3/林俊杰 – 曹操.mp3”
  11.             }).jPlayer(“play”);
  12.         },
  13.         timeupdate: function(event) {
  14.              if(event.jPlayer.status.currentTime==0){
  15.                 if(isiOS==true){
    time = 0;
    }else{
    time = “”;
    }
  16.              }else {
  17.                 time = event.jPlayer.status.currentTime;
  18.              }
  19.         },
  20.         play: function(event) {
  21.             //点击开始方法调用lrc.start歌词方法 返回时间time
  22.             if($(‘#lrc_content’).val()!==””){
  23.                 $.lrc.start(function(){
  24.                     return time;
  25.                 });
  26.             }else{
  27.              $(“.content”).html(“没有字幕”);
  28.             }
  29.         },
  30.         swfPath: “js”,
  31.         supplied: “mp3”,
  32.         wmode: “window”,
  33.         smoothPlayBar: true,
  34.         keyEnabled: true,
  35.         remainingDuration: true,
  36.         toggleDuration: true
  37.     });
  38. });

 

5、这一步不是必要的 只是提供一个我的源码给你们参考:

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title>完整jplayer歌词同步demo</title>
  5. <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8” />
  6. <link href=“skin/pink.flag/jplayer.pink.flag.css” rel=“stylesheet” type=“text/css” />
  7. <script type=“text/javascript” src=“js/jquery-1.8.2.min.js”></script>
  8. <script type=“text/javascript” src=“js/jquery.jplayer.min.js”></script>
  9. <script type=“text/javascript” src=“js/jquery.jplayer.lyric.js”></script>
  10. <style type=“text/css”>
  11. *{ margin:0; padding:0; }
  12. ul, ol, dl { list-style:none; }
  13. .content li.hover{color:red; }
  14. .content{ width:200px;overflow:hidden;padding:10px; text-align: center; font-size:12px;}
  15. </style>
  16. <script type=“text/javascript”>
  17. //<![CDATA[
  18. var u = navigator.userAgent;
  19. var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  20. $(document).ready(function(){
  21.     $(“#jquery_jplayer_1”).jPlayer({
  22.         ready: function () {
  23.             //初始化歌词信息(传入歌词文件文本)
  24.             $.lrc.init($(‘#lrc_content’).val());
  25.             $(this).jPlayer(“setMedia”, {
  26.                 title: “Bubble”,
  27.                 mp3: “mp3/林俊杰 – 曹操.mp3”
  28.             }).jPlayer(“play”);
  29.         },
  30.         timeupdate: function(event) {
  31.              if(event.jPlayer.status.currentTime==0){
  32.                     if(isiOS==true){
    time = 0;
    }else{
    time = “”;
    }
  33.              }else {
  34.                 time = event.jPlayer.status.currentTime;
  35.              }
  36.         },
  37.         play: function(event) {
  38.             //点击开始方法调用lrc.start歌词方法 返回时间time
  39.             if($(‘#lrc_content’).val()!==””){
  40.                 $.lrc.start(function(){
  41.                     return time;
  42.                 });
  43.             }else{
  44.              $(“.content”).html(“没有字幕”);
  45.             }
  46.         },
  47.         swfPath: “js”,
  48.         supplied: “mp3”,
  49.         wmode: “window”,
  50.         smoothPlayBar: true,
  51.         keyEnabled: true,
  52.         remainingDuration: true,
  53.         toggleDuration: true
  54.     });
  55. });
  56. //]]>
  57. </script>
  58. </head>
  59. <body>
  60. <!–textarea只是用来存储歌词信息 并不做显示,如果要修改显示样式,修改id=”lrc_list”的样式就行–>
  61. <textarea id=“lrc_content” style=“display:none;”>
  62. [ti:曹操]
  63. [ar:林俊杰]
  64. [al:曹操]
  65. [00:00.03]林俊杰-《曹操》
  66. [00:13.35]作词:林秋离
  67. [00:20.12]作曲:林俊杰
  68. [00:25.32]
  69. [01:33.46][00:26.82]不是英雄 不读三国
  70. [01:40.12][00:33.43]若是英雄 怎么能不懂寂寞
  71. [02:39.68][01:46.34][00:39.63]独自走下长坂坡 月光太温柔
  72. [02:43.20][01:49.82][00:43.15]曹操不啰嗦 一心要那荆州
  73. [02:46.75][01:53.48][00:46.83]用阴谋 阳谋 明说 暗夺的摸
  74. [02:53.44][02:00.10][00:53.50]东汉末年分三国
  75. [02:56.37][02:03.15][00:56.52]烽火连天不休
  76. [03:00.12][02:06.75][01:00.17]儿女情长 被乱世左右
  77. [03:05.04][02:11.71][01:05.12]谁来煮酒
  78. [03:06.78][02:13.45][01:06.84]尔虞我诈是三国
  79. [03:09.85][02:16.43][01:09.73]说不清对与错
  80. [03:13.38][02:20.11][01:13.48]纷纷扰扰 千百年以後
  81. [03:18.44][02:25.06][01:18.45]一切又从头
  82. [03:25.99][02:30.17][01:26.81]喔……
  83. [88:88:88]
  84. </textarea>
  85. <div id=“jquery_jplayer_1” class=“jp-jplayer”></div>
  86. <div id=“jp_container_1” class=“jp-audio”>
  87.     <div class=“jp-type-single”>
  88.         <div class=“jp-gui jp-interface”>
  89.             <ul class=“jp-controls”>
  90.                 <li><a href=“javascript:;” class=“jp-play” tabindex=“1”>play</a></li>
  91.                 <li><a href=“javascript:;” class=“jp-pause” tabindex=“1”>pause</a></li>
  92.                 <li><a href=“javascript:;” class=“jp-stop” tabindex=“1”>stop</a></li>
  93.                 <li><a href=“javascript:;” class=“jp-mute” tabindex=“1” title=“mute”>mute</a></li>
  94.                 <li><a href=“javascript:;” class=“jp-unmute” tabindex=“1” title=“unmute”>unmute</a></li>
  95.                 <li><a href=“javascript:;” class=“jp-volume-max” tabindex=“1” title=“max volume”>max volume</a></li>
  96.             </ul>
  97.             <div class=“jp-progress”>
  98.                 <div class=“jp-seek-bar”>
  99.                     <div class=“jp-play-bar”></div>
  100.                 </div>
  101.             </div>
  102.             <div class=“jp-volume-bar”>
  103.                 <div class=“jp-volume-bar-value”></div>
  104.             </div>
  105.             <div class=“jp-current-time”></div>
  106.             <div class=“jp-duration”></div>
  107.             <ul class=“jp-toggles”>
  108.                 <li><a href=“javascript:;” class=“jp-repeat” tabindex=“1” title=“repeat”>repeat</a></li>
  109.                 <li><a href=“javascript:;” class=“jp-repeat-off” tabindex=“1” title=“repeat off”>repeat off</a></li>
  110.             </ul>
  111.         </div>
  112.         <div class=“jp-details”>
  113.             <ul>
  114.                 <li><span class=“jp-title”></span></li>
  115.             </ul>
  116.         </div>
  117.         <div class=“jp-no-solution”>
  118.             <span>Update Required</span>
  119.             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>.
  120.         </div>
  121.     </div>
  122. </div>
  123. <div class=“content”>
  124.     <ul id=“lrc_list”>
  125.         加载歌词……
  126.     </ul>
  127. </div>
  128. </body>
  129. </html>

 

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论