歌词联动

  1. <%@ page language= "java" pageEncoding= "UTF-8"%>
  2. <% String path = request.getContextPath(); %>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4. <html xmlns= "http://www.w3.org/1999/xhtml">
  5. <head>
  6. <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" />
  7. <title>jplayer实现滚动歌词 </title>
  8. <link href= "<%=path%>/Jplayer/skin/blue.monday/jplayer.blue.monday.css" rel= "stylesheet" type= "text/css" />
  9. <script type= "text/javascript" src= "http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
  10. <script type= "text/javascript" src= "<%=path%>/Jplayer/js/jquery.jplayer.min.js"></script>
  11. <script type= "text/javascript">
  12. var playTime;
  13. window.lrc_obj = null;
  14. $(document).ready(function() {
  15. $( "#jquery_jplayer_1").jPlayer({
  16. ready: function () {
  17. var lrc= "[ar:姜玉阳][ti:痛彻心扉][00:02.43]痛彻心扉[00:07.67]制作 曾经拥有[00:13.81]希望你快乐 QQ511277376[00:28.03]怎么能够让我不再想你[00:36.00]也许爱你爱到最后只能伤心[00:42.76]已经有了离开你的勇气[00:48.44]在我的梦里你不是唯一[00:55.50]我想要再回到你温暖的怀里[01:02.31]感觉你的心跳你的呼吸[01:08.96]想到天长地久对于我们[01:13.38]渴望而不可及[01:15.92]难道命运注定就此分离[01:26.28]爱你 痛彻我心扉[01:32.27]给了你 仅有的一片天[01:38.47]回忆的碎片[01:40.85]撞翻我心中思念的火蕊[01:45.83]燃烧我整座的堡垒[01:51.42]爱你 痛彻我心扉[01:58.88]少了你 还残留一片天[02:05.13]我想我只会[02:07.57]紧握住手中凋零的玫瑰[02:12.64]品尝你赐给的泪水[02:18.89]或许你曾为我流泪[02:25.44]如今你让我痛彻心扉[02:48.09]我想要再回到你温暖的怀里[03:05.66]感觉你的心跳你的呼吸[03:12.21]想到天长地久对于我们[03:16.83]渴望而不可及[03:19.27]难道命运注定就此分离[03:29.38]爱你 痛彻我心扉[03:35.62]给了你 仅有的一片天[03:41.82]回忆的碎片[03:44.26]撞翻我心中思念的火蕊[03:49.29]燃烧我整座的堡垒[03:56.45]爱你 痛彻我心扉[04:02.19]少了你 还残留一片天[04:08.43]我想我只会[04:10.87]紧握住手中凋零的玫瑰[04:15.90]品尝你赐给的泪水[04:22.20]或许你曾为我流泪[04:28.90]如今你让我痛彻心扉[04:35.55]如今你让我痛彻心扉";
  18. change_lrc(lrc);
  19. $( this).jPlayer( "setMedia", {
  20. mp3: '<%=path%>/Jplayer/mp3/2.mp3'
  21. }).jPlayer( "play");
  22. },
  23. timeupdate : function (obj){
  24. show_lrc(obj.jPlayer.status.currentTime);
  25. playTime = obj.jPlayer.status.currentTime;
  26. },
  27. ended: function (event) {
  28. $( this).jPlayer( "play");
  29. },
  30. swfPath: "<%=path%>/Jplayer/js",
  31. supplied: "mp3,oga",
  32. wmode: "window"
  33. });
  34. });
  35. //把歌词转换成时间和歌词内容的一个数组
  36. function change_lrc (data)
  37. {
  38. //alert(data);
  39. window.lrc_item = - 1; //重置歌词下标
  40. $( '#lrc_panel').html( '歌词解析中...');
  41. var lrc = [{time: 0, lrc: ''}];
  42. var match = data.match(/\[ *ti *\:([^\[\]]+)\]/i);
  43. if (match) lrc[ 0].lrc += '歌名:' + match[ 1] + "<br/>"; //歌名
  44. var match = data.match(/\[ *ar *\:([^\[\]]+)\]/i);
  45. if (match) lrc[ 0].lrc += '词:' + match[ 1] + "<br/>"; //作词
  46. var match = data.match(/\[ *cm *\:([^\[\]]+)\]/i);
  47. if (match) lrc[ 0].lrc += '曲:' + match[ 1] + "<br/>"; //作曲
  48. var match = data.match(/\[ *al *\:([^\[\]]+)\]/i);
  49. if (match) lrc[ 0].lrc += '  专辑:' + match[ 1] + "<br/>"; //专辑
  50. var match = data.match(/\[ *sr *\:([^\[\]]+)\]/i);
  51. if (match) lrc[ 0].lrc += '  歌手:' + match[ 1] + "<br/>"; //歌手
  52. var offset = 0;
  53. var match = data.match(/\[ *offset *\:(\d+)\]/i);
  54. if (match) offset = match[ 1] / 1000; //时间调整
  55. var match = data.match(/(\[ *[\d\:\.]+ *\][^\[\]]+)/g);
  56. if (match){
  57. for (var i = 0; i < match.length; i++){
  58. //alert(match[i]);
  59. var temp = match[i].split( ']');
  60. var temp_lrc = temp[ 1];
  61. temp = temp[ 0].replace( '[', '');
  62. temp = temp.split( ':');
  63. var time = 0;
  64. time += temp[temp.length - 1] * 1; //秒
  65. if (temp.length > 1) time += temp[temp.length - 2] * 60; ///分
  66. if (temp.length > 2) time += temp[temp.length - 3] * 3600; ///时
  67. if (time != 0) time += offset; //只有非0歌词才有必要加调整;
  68. //alert(time + ':' + temp_lrc);
  69. if (lrc[lrc.length - 1].time == time) lrc[lrc.length - 1].lrc += '  ' + temp_lrc + "<br/>"; //相同时间合并
  70. else lrc[lrc.length] = {time:time, lrc:temp_lrc + "<br/>"}; //按获取顺序记录,如果lrc是乱序将导致后面显示错误
  71. }
  72. }
  73. window.lrc_obj = lrc; //处理好再复制
  74. //alert(lrc[57].lrc);
  75. show_lrc ( 0); //显示歌曲信息
  76. }
  77. /*
  78. * 显示歌词,并得到正在播放歌词的下标,
  79. * param:sec 歌词对应的秒.
  80. */
  81. function show_lrc (sec){
  82. if (!window.lrc_obj) return 0;
  83. if ( window.lrc_obj[window.lrc_obj.length- 1].time < sec ){
  84. if (window.lrc_item < window.lrc_obj.length){
  85. window.lrc_item = window.lrc_obj.length;
  86. center_lrc(window.lrc_obj.length - 1); //显示尾句
  87. }
  88. return 0; //显示到最后一句
  89. } else if (window.lrc_item < 0){ //初始化,且需要刷新歌词
  90. window.lrc_item = 1;
  91. center_lrc( 0); //显示第一句
  92. if (sec < window.lrc_obj[window.lrc_item].time) return 0; //处于第二句前
  93. }
  94. if ( (window.lrc_obj[window.lrc_item - 1].time <= sec) && (sec < window.lrc_obj[window.lrc_item].time) ){
  95. return 0; //当前时间处于当前显示句之后,后一句之前,无需要刷新歌词
  96. }
  97. if (window.lrc_obj[window.lrc_item].time < sec){ //歌词过时了,自动播放或拉进度到后面
  98. do
  99. {
  100. window.lrc_item++;
  101. } while ( (window.lrc_item <= window.lrc_obj.length) && (window.lrc_obj[window.lrc_item].time < sec) )
  102. center_lrc(window.lrc_item - 1); //显示后面对应一句
  103. return 0;
  104. } else{ //歌词过快,如拉前了
  105. do
  106. {
  107. window.lrc_item--;
  108. } while ( ( 0 <= window.lrc_item) && (sec < window.lrc_obj[window.lrc_item].time) )
  109. window.lrc_item++;
  110. center_lrc(window.lrc_item - 1); //显示前面对应一句
  111. return 0;
  112. }
  113. }
  114. /*
  115. * 得到正在播放的歌词
  116. * index 是数组的下标值.
  117. */
  118. function center_lrc(index)
  119. {
  120. if (! window.lrc_obj || (index >= window.lrc_obj.length ) || (index < 0) ) return 0;
  121. var padding = 10; //居中头尾个数
  122. var lrc_html = '';
  123. for(var m = 0; m <= window.lrc_obj.length - 1; m++) {
  124. if(index != m) {
  125. if(window.lrc_obj[m].lrc == '') {
  126. lrc_html += '<li style= "list-style-type:none;">........</li>';
  127. } else {
  128. lrc_html += '<li style= "list-style-type:none;">' + window.lrc_obj[m].lrc + '</li>';
  129. }
  130. } else if(index == m) {
  131. if(window.lrc_obj[m].lrc == '') {
  132. lrc_html += '<li id="crly" style= "list-style-type:none;"><font color="blue">........</font></li>';
  133. } else {
  134. lrc_html += '<li id="crly" style= "list-style-type:none;"><font color="purple">' + window.lrc_obj[m].lrc + '</font></li>';
  135. }
  136. }
  137. }
  138. //var lp = document.getElementById('lyrics');
  139. //lp.scrollTop=lp.scrollHeight;
  140. //alert(lrc_html);
  141. $( '#lrc_panel').get( 0).innerHTML = lrc_html;
  142. var lp = document.getElementById( "lyrics");
  143. var lh = $( "#crly").position().top;
  144. lp.scrollTop+=parseInt(lh) - 80;
  145. }
  146. </script>
  147. <style>
  148. <!--
  149. .lyrics{
  150. font-size: 13px;
  151. color:#f7b607
  152. }
  153. -->
  154. </style>
  155. </head>
  156. <body>
  157. <div style= "float: left">
  158. <div id= "jquery_jplayer_1" class= "jp-jplayer"></div>
  159. <div id= "jp_container_1" class= "jp-audio">
  160. <div class= "jp-type-single">
  161. <div class= "jp-gui jp-interface">
  162. <ul class= "jp-controls">
  163. <li><a href= "javascript:;" class= "jp-play" tabindex= "1">play</a></li>
  164. <li><a href= "javascript:;" class= "jp-pause" tabindex= "1">pause</a></li>
  165. <li><a href= "javascript:;" class= "jp-stop" tabindex= "1">stop</a></li>
  166. <li><a href= "javascript:;" class= "jp-mute" tabindex= "1" title= "mute">mute</a></li>
  167. <li><a href= "javascript:;" class= "jp-unmute" tabindex= "1" title= "unmute">unmute</a></li>
  168. <li><a href= "javascript:;" class= "jp-volume-max" tabindex= "1" title= "max volume">max volume</a></li>
  169. </ul>
  170. <div class= "jp-progress">
  171. <div class= "jp-seek-bar">
  172. <div class= "jp-play-bar"></div>
  173. </div>
  174. </div>
  175. <div class= "jp-volume-bar">
  176. <div class= "jp-volume-bar-value"></div>
  177. </div>
  178. <div class= "jp-time-holder">
  179. <div class= "jp-current-time"></div>
  180. <div class= "jp-duration"></div>
  181. <ul class= "jp-toggles">
  182. <li><a href= "javascript:;" class= "jp-repeat" tabindex= "1" title= "repeat">repeat</a></li>
  183. <li><a href= "javascript:;" class= "jp-repeat-off" tabindex= "1" title= "repeat off">repeat off</a></li>
  184. </ul>
  185. </div>
  186. </div>
  187. <div class= "jp-title">
  188. <ul>
  189. <li>痛彻心扉</li>
  190. </ul>
  191. </div>
  192. <div class= "jp-no-solution">
  193. <span>Update Required</span>
  194. 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>.
  195. </div>
  196. </div>
  197. </div>
  198. </div>
  199. <div class= "lyrics" id= "lyrics" style= "overflow: scroll; width: 255px; height: 275px; float:right">
  200. <strong></strong>
  201. <ul id= "lrc_panel" ></ul>
  202. </div>
  203. </body>
  204. </html>
### 鸿蒙系统中实现音乐播放时 KRC 歌词与进度条联动的功能 要在鸿蒙系统中实现音乐播放时 KRC 歌词与进度条的联动功能,主要涉及以下几个方面: #### 1. 解析 KRC 文件 KRC 文件是一种特殊的歌词格式,通常用于逐字高亮显示歌词。由于其内容经过加密处理,直接读取会呈现乱码[^2]。因此,在实现过程中需要先解密 KRC 文件并将其转换为可使用的 LRC 格式。 以下是 PHP 中解析 KRC 文件的一个示例代码片段,可以作为参考来编写适用于 HarmonyOS 的逻辑: ```javascript // 假设已获取到 KRC 文件的内容 function decryptKrc($encryptedData) { // 对 KRC 数据进行解密操作 (具体算法需根据实际需求调整) $decryptedData = someDecryptionAlgorithm($encryptedData); // 将解密后的数据转化为标准 LRC 格式的字符串 let lrcContent = convertToLrcFormat(decryptedData); return lrcContent; } ``` 注意:具体的解密算法可能因平台而异,建议查阅相关文档或开源库以获得更精确的方法[^3]。 #### 2. 同步歌词时间戳与音频播放位置 为了使歌词能够随着音乐播放自动滚动并与进度条保持一致,需要监听当前音频播放的时间点,并更新对应的歌词行以及进度条的位置。 可以通过设置定时器或者利用媒体播放框架中的回调函数完成这一目标。例如,在 JavaScript 或 Java 编程环境中,可以采用如下方式实现: ```java mediaPlayer.setOnTimeUpdateListener(new MediaPlayer.OnTimeUpdateListener() { @Override public void onTimeUpdated(long currentTimeMs) { String currentLine = findLyricByTimestamp(currentTimeMs); // 查找对应时间戳的歌词行 updateProgressBar(currentTimeMs); // 更新进度条状态 highlightCurrentLyric(currentLine); // 高亮当前歌词行 } }); ``` 其中 `findLyricByTimestamp` 方法负责依据当前播放时间查找匹配的歌词行;`updateProgressBar` 和 `highlightCurrentLyric` 则分别用来刷新 UI 组件的状态。 #### 3. 动态更新界面元素 当检测到新的歌词行应该被展示时,及时修改视图上的文字内容及其样式属性(比如颜色变化)。同时也要确保整个过程流畅无卡顿现象发生。 对于 HarmonyOS 应用而言,推荐使用 AbilitySlice 结构化布局配合 XML 定义静态资源文件的方式构建用户交互界面。并通过 DataBinding 技术绑定动态数据源至控件实例上从而简化编码流程提高效率。 --- ### 总结 通过以上三个步骤即可成功达成在鸿蒙设备上面向用户提供带有精准同步效果的支持 krc 类型歌词的服务体验。需要注意的是实际开发当中还可能存在其他细节问题等待解决如网络请求异常情况下的错误提示机制设计等等都需要开发者自行斟酌完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值