效果图: 歌词会随播放滚动

html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon" /> <link rel="stylesheet" href="./css/index.css" /> </head> <style> * { margin: 0; padding: 0; } body { background: #000; color: #666; text-align: center; } audio { width: 450px; margin: 30px 0; } .container { height: 420px; overflow: hidden; /* border: 2px solid #fff; */ } .container ul { /* border: 2px solid #fff; */ transition: 0.6s; list-style: none; } .container li { height: 30px; /* border: 1px solid #fff; */ line-height: 30px; transition: 0.2s; } .container li.active { color: #fff; /* font-size: ; */ transform: scale(1.2); } </style> <body> <audio controls src="./assets/music.mp3"></audio> <div class="container"> <ul class="lrc-list"></ul> </div> //引入的歌词文件 <script src="./js/data.js"></script> <!-- <script src="./js/index.js"></script> --> </body> <script> /** * 解析歌词字符串 * 得到一个歌词对象的数组 * 每个歌词对象: * {time:开始时间,words:歌词内容} */ // [00:01.06]难念的经 function parseLrc() { console.log(lrc); // 1. 分割字符串,得到一个数组 var lines = lrc.split('\n'); //存放歌词对象的数组 var result = []; //循环遍历数组,拿到每一行的字符串 for (var i = 0; i < lines.length; i++) { var str = lines[i]; //分割字符串 var parts = str.split(']'); //截取时间 var timeStr = parts[0].substring(1); //添加一个对象 var obj = { time: parseTime(timeStr), words: parts[1] || '', }; result.push(obj); //得到{time: 229.99, words: '天阔阔雪漫漫共谁同航'} } return result; } /** * 将时间字符串转换为秒数 * @param {string} timeStr 时间字符串,格式为"mm:ss" * @returns {number} 返回转换后的秒数 */ function parseTime(timeStr) { var parts = timeStr.split(':'); return +parts[0] * 60 + +parts[1]; } var lrcData = parseLrc(); //获取需要的dom var doms = { audio: document.querySelector('audio'), ul: document.querySelector('.container ul'), container: document.querySelector('.container'), }; /** * 计算出,在当前播放器播放到第几秒的情况下 * lrcData数组中,应该高亮显示的歌词下标 * 如果没有任何一句歌词需要显示,则得到-1 */ function findIndex() { //获取当前播放器的时间 var curTime = doms.audio.currentTime; //遍历lrcData数组 for (var i = 0; i < lrcData.length; i++) { console.log('i', lrcData[i]); //如果当前时间小于lrcData[i].time //说明当前时间还没有到达这一句歌词的开始时间 //此时,应该高亮显示的歌词下标就是i-1 if (curTime < lrcData[i].time) { return i - 1; } } //找遍了都没找到(说明播放到最后一句) return lrcData.length - 1; } //界面 创建歌词元素 li function createLrcElements() { //文档片段 var frag = document.createDocumentFragment(); for (var i = 0; i < lrcData.length; i++) { var li = document.createElement('li'); li.innerText = lrcData[i].words; //添加到ul中, 改动了 dom 树 // doms.ul.appendChild(li); frag.appendChild(li); } doms.ul.appendChild(frag); } createLrcElements(); //尺寸信息 //容器高度 var containerHeight = doms.container.clientHeight; // 每个li的高度 var liHeight = doms.ul.children[0].clientHeight; //最大偏移量 var maxOffset = doms.ul.clientHeight - containerHeight; //设置 ul 元素的偏移量 function setOffset() { console.log('调用了 setOffset'); //获取当前需要高亮显示的歌词下标 var index = findIndex(); //偏移量计算 var offset = liHeight * index + liHeight / 2 - //容器的一半 containerHeight / 2; console.log('偏移量', offset); //边界判断 最小值 if (offset < 0) { offset = 0; } if (offset > maxOffset) { offset = maxOffset; } doms.ul.style.transform = `translateY(-${offset}px)`; //去掉之前的active样式 var li = doms.ul.querySelector('.active'); if (li) { li.classList.remove('active'); } //重新获取需要高亮显示的li li = doms.ul.children[index]; if (li) { li.classList.add('active'); } } //时间改变的事件 doms.audio.addEventListener('timeupdate', setOffset //每次播放器时间更新,都需要重新计算偏移量 ); //初始偏移量 setOffset(); </script> </html>
歌词
var lrc = `[00:01.06]难念的经
00:03.95\]演唱:周华健 \[00:06.78
00:30.96\]笑你我枉花光心计 \[00:34.15\]爱竞逐镜花那美丽 \[00:36.75\]怕幸运会转眼远逝 \[00:39.32\]为贪嗔喜恶怒着迷 \[00:41.99\]责你我太贪功恋势 \[00:44.48\]怪大地众生太美丽 \[00:47.00\]悔旧日太执信约誓 \[00:49.66\]为悲欢哀怨妒着迷 \[00:52.56\]啊 舍不得璀灿俗世 \[00:57.66\]啊 躲不开痴恋的欣慰 \[01:02.86\]啊 找不到色相代替 \[01:08.09\]啊 参一生参不透这条难题 \[01:13.15\]吞风吻雨葬落日未曾彷徨 \[01:15.73\]欺山赶海践雪径也未绝望 \[01:18.23\]拈花把酒偏折煞世人情狂 \[01:20.90\]凭这两眼与百臂或千手不能防 \[01:23.76\]天阔阔雪漫漫共谁同航 \[01:26.09\]这沙滚滚水皱皱笑着浪荡 \[01:28.68\]贪欢一刻偏教那女儿情长埋葬 \[01:32.38
01:34.09\]吞风吻雨葬落日未曾彷徨 \[01:36.50\]欺山赶海践雪径也未绝望 \[01:39.07\]拈花把酒偏折煞世人情狂 \[01:41.69\]凭这两眼与百臂或千手不能防 \[01:44.68\]天阔阔雪漫漫共谁同航 \[01:46.93\]这沙滚滚水皱皱笑着浪荡 \[01:49.54\]贪欢一刻偏教那女儿情长埋葬 \[01:53.41
02:15.45\]笑你我枉花光心计 \[02:18.53\]爱竞逐镜花那美丽 \[02:21.14\]怕幸运会转眼远逝 \[02:23.76\]为贪嗔喜恶怒着迷 \[02:26.43\]责你我太贪功恋势 \[02:28.98\]怪大地众生太美丽 \[02:31.60\]悔旧日太执信约誓 \[02:34.26\]为悲欢哀怨妒着迷 \[02:36.90\]啊 舍不得璀灿俗世 \[02:42.04\]啊 躲不开痴恋的欣慰 \[02:47.34\]啊 找不到色相代替 \[02:52.52\]啊 参一生参不透这条难题 \[02:57.47\]吞风吻雨葬落日未曾彷徨 \[03:00.05\]欺山赶海践雪径也未绝望 \[03:02.64\]拈花把酒偏折煞世人情狂 \[03:05.27\]凭这两眼与百臂或千手不能防 \[03:08.22\]天阔阔雪漫漫共谁同航 \[03:10.49\]这沙滚滚水皱皱笑着浪荡 \[03:13.06\]贪欢一刻偏教那女儿情长埋葬 \[03:18.45\]吞风吻雨葬落日未曾彷徨 \[03:20.90\]欺山赶海践雪径也未绝望 \[03:23.54\]拈花把酒偏折煞世人情狂 \[03:26.21\]凭这两眼与百臂或千手不能防 \[03:29.07\]天阔阔雪漫漫共谁同航 \[03:31.32\]这沙滚滚水皱皱笑着浪荡 \[03:33.92\]贪欢一刻偏教那女儿情长埋葬 \[03:39.32\]吞风吻雨葬落日未曾彷徨 \[03:41.84\]欺山赶海践雪径也未绝望 \[03:44.38\]拈花把酒偏折煞世人情狂 \[03:47.04\]凭这两眼与百臂或千手不能防 \[03:49.99\]天阔阔雪漫漫共谁同航 \[03:52.20\]这沙滚滚水皱皱笑着浪荡 \[03:54.89\]贪欢一刻偏教那女儿情长埋葬 \[04:00.28\]吞风吻雨葬落日未曾彷徨 \[04:02.68\]欺山赶海践雪径也未绝望 \[04:05.25\]拈花把酒偏折煞世人情狂 \[04:07.90\]凭这两眼与百臂或千手不能防 \[04:10.85\]天阔阔雪漫漫共谁同航 \[04:13.08\]这沙滚滚水皱皱笑着浪荡 \[04:15.75\]贪欢一刻偏教那女儿情长埋葬 \[04:19.48\]\`;