首先需要整理好lrc格式的歌词放到script标签中以供程序处理。然后把音乐链接放到audio的src属性里就可以了。
源码:
HTML部分
1 <div class="container"> 2 <audio id="player" src="test.mp3" loop controls preload></audio> 3 <div id="lrcArea"></div> 4 </div> 5 6 <script id="lrc" type="text"> 7 //lrc歌词 8 </script>
JS部分
1 var musicPlayer = function() { 2 return this.init.apply(this, arguments); 3 }; 4 5 musicPlayer.prototype = { 6 constructor: musicPlayer, 7 init: function(options) { 8 if (isEmptyObj(options) || typeof options !== 'object') return; 9 this.player = options.player; 10 this.lrc = options.lrc; 11 this.lrcArea = options.lrcArea; 12 //用于保存歌词 13 this.lrcArr = []; 14 //用于保存时间戳 15 this.timestamp = []; 16 //处理歌词 17 this.handleLrc(this.lrc); 18 var that = this; 19 20 this.player.addEventListener('play', 21 function() { 22 that.play(); 23 }, 24 false); 25 26 this.player.addEventListener('pause', 27 function() { 28 that.pause(); 29 }, 30 false); 31 32 //歌词索引 33 this.idx = 0; 34 }, 35 //格式化歌词 36 handleLrc: function(lrc) { 37 var re = /([.+])(.+)?/gm, 38 ul = cEl('ul'), 39 frag = document.createDocumentFragment(), 40 tmpArr, 41 i, 42 len; 43 this.lrcArea.innerHTML = ''; 44 frag.appendChild(ul); 45 ul.id = 'c'; 46 this.lrcArea.appendChild(frag); 47 48 var txt = lrc.replace(re, 49 function(a, b, c) { 50 return b + (c === undefined ? ' ': c) + ' '; 51 }); 52 53 tmpArr = txt.split(' '); 54 55 //处理歌词 56 for (i = 0, len = tmpArr.length; i < len; i++) { 57 var item = trim(tmpArr[i]); 58 if (item.length > 0) { 59 this.lrcArr.push(item); 60 } 61 } 62 63 frag = document.createDocumentFragment(); 64 65 for (i = 0, len = this.lrcArr.length; i < len; i++) { 66 var li = cEl('li'); 67 if (i === 0) { 68 li.className = 'cur'; 69 } 70 li.innerHTML = this.lrcArr[i].replace(/[.+]/i, ''); 71 //处理时间 72 this.timestamp.push(this.lrcArr[i].replace(re, 73 function(a, b, c) { 74 return b; 75 }).replace('[', '').replace(']', '')); 76 frag.appendChild(li); 77 } 78 79 ul.appendChild(frag); 80 this.li = $('lrcArea').getElementsByTagName('li'); 81 }, 82 //播放 83 play: function() { 84 this.stop = false; 85 var that = this, 86 player = this.player, 87 i, len; 88 89 this.t = setInterval(function() { 90 if (that.stop) return; 91 that.curTime = player.currentTime; 92 93 for (i = 0, len = that.timestamp.length - 1; i < len; i++) { 94 var prevTime = that.formatTimeStamp(that.timestamp[i]), 95 nextTime = that.formatTimeStamp(that.timestamp[i + 1]); 96 //当前播放时间与前后歌词时间比较,如果位于这两者之间则转到该歌词 97 if (parseFloat(that.curTime) > prevTime && parseFloat(that.curTime) < nextTime) { 98 that.scrollToLrc(i); 99 return; 100 } 101 } 102 }, 103 300); 104 }, 105 //暂停 106 pause: function() { 107 this.stop = true; 108 clearInterval(this.t); 109 }, 110 //格式化时间 111 formatTimeStamp: function(timestamp) { 112 var re = /([0-9]+):([0-9]+).([0-9]+)/i, 113 seconds = timestamp.replace(re, 114 function(a, b, c, d) { 115 return Number(b * 60) + Number(c) + parseFloat('0.' + d); 116 }); 117 return seconds; 118 }, 119 //歌词滚动 120 scrollToLrc: function(idx) { 121 var ds = getOffset(this.li[idx]).top, 122 i, 123 len; 124 //如果歌词索引没有变动,则认为这句没有唱完,不处理 125 if (this.idx === idx) return; 126 //否则更新索引值并更新样式和位置 127 this.idx = idx; 128 for (i = 0, len = this.li.length; i < len; i++) { 129 this.li[i].className = ''; 130 } 131 this.li[idx].className = 'cur'; 132 this.lrcArea.scrollTop = ds - this.lrcArea.offsetHeight / 2; 133 } 134 }; 135 136 function $(id) { 137 return typeof id === 'string' ? document.getElementById(id) : id; 138 } 139 function cEl(el) { 140 return document.createElement(el); 141 } 142 function trim(str) { 143 return str.replace(/(^s*)|(s*$)/g, ""); 144 } 145 function isEmptyObj(o) { 146 for (var p in o) return false; 147 return true; 148 } 149 function getOffset(el) { 150 var parent = el.offsetParent, 151 left = el.offsetLeft, 152 top = el.offsetTop; 153 154 while (parent !== null) { 155 left += parent.offsetLeft; 156 top += parent.offsetTop; 157 parent = parent.offsetParent; 158 } 159 160 return { 161 left: left, 162 top: top 163 }; 164 } 165 166 var p = new musicPlayer({ 167 player: $('player'), 168 lrc: $('lrc').innerHTML, 169 lrcArea: $('lrcArea') 170 });