首先需要整理好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.;
46 this.lrcArea.appendChild(frag);
47
48 var txt = lrc.replace(re,
49 function(a, b, c) {
50 return b + (c === undefined ? ' ': c) + '\n';
51 });
52
53 tmpArr = txt.split('\n');
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 });
View Code