1.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">
    <!-- 引入css -->
    <link rel="stylesheet" href="./index.css">
    
</head>
<body>
    <audio src="./assets/music.mp3" controls></audio>
   <div class="container">
    <ul class="lrc-list">
          <!-- li由js动态创建,此处只是为了方便观看,可删掉 -->
        <li>Fuga nemo ut perspiciatis.</li>
    </ul>
   </div>
       <!-- 引入歌词部分 -->
       <script src="./js/data.js"></script>
       <script src="./index.js"></script>
</body>
</html>

2.css部分完整代码

*{
    margin: 0;
    padding: 0;
}
body{
    background-color: black;
    color: #6b6a6a;
    text-align: center;
}
audio{
    margin: 10px 0;
    width: 450px;
}
.container{
    border: 1px solid red;
    height: 400px;
    overflow: hidden;
}
.container ul{
 border: 1px solid rgb(221, 203, 203);
 /* 滚动动画过渡时间 */
transition: 0.5s;
/* 歌词向上滚动偏移,用js来控制 */
transform: translateY(0px);
}
.container li{
list-style: none;
text-align: center;
left: 30px;
height: 30px;
/* 激活样式过度时间 */
transition: 0.4s;

}
.container li.active{
color: #fff;
/* 激活字体放大,使用transform比font-size性能更好 */
transform: scale(1.5) ;
}

3.js部分代码详解

      0.获取dom元素

html5 歌词单击 歌词滚动的html代码_数组

      1.先解析歌词字符串为数组

html5 歌词单击 歌词滚动的html代码_javascript_02

     2. 计算出,在当前播放器播放到第几秒的情况下, lcrData数组中,应该高亮显示歌词下标,如 果没有歌词需要显示则得到-1

html5 歌词单击 歌词滚动的html代码_html_03

      3.创建歌词元素

  

html5 歌词单击 歌词滚动的html代码_html_04

 4.歌词滚动偏移量计算

           4.1图解

html5 歌词单击 歌词滚动的html代码_html5 歌词单击_05

       4.2代码分解

 

html5 歌词单击 歌词滚动的html代码_html_06

5.js部分完整代码

//获取dom元素
let doms = {
    ul: document.querySelector("ul"),
    audio: document.querySelector("audio"),
    container: document.querySelector(".container")
}
/**
 * 解析歌词字符串
 * 得到一个歌词对象的数组
 * 每个歌词对象
 * {time:歌词开始的时间,words:歌词内容}
 */
function parseLrc() {
    let lcrArr = []//定义空变量保存数组
    let lines = lrc.split("\n")//以换行分隔符把歌词转为数组
    for (let i = 0; i < lines.length; i++) { //循环得到数组的每一项
        let parseSrc = lines[i].split("]")//把数组每一项拆分为数组
        let timeSrc = parseSrc[0].substring(1)//获取到时间字符串
        let obj = {                           //拼接对象
            tiem: parseTime(timeSrc),
            words: parseSrc[1]
        }
        lcrArr.push(obj)       //把对象添加到数组中  
    }
    return lcrArr

}


/**
 * 将一个时间字符串处理为数字(秒)
 * @param timeStr 时间字符串
 * @returns 返回数字
 */
function parseTime(time) {
    let tiemArr = time.split(":")//把时间字符串拆分为数组
    return tiemArr[0] * 60 + +tiemArr[1] //返回具体的数字时间 +运算符可以把字符串转成数字
}

let lrcData = parseLrc()
console.log(lrcData)

/**
 * 计算出,在当前播放器播放到第几秒的情况下
 * lcrData数组中,应该高亮显示歌词下标
 * 如果没有歌词需要显示则得到-1
 */
function findIndex() {
    let currentTime = doms.audio.currentTime//当前播放时间
    for (let i = 0; i < lrcData.length; i++) {
        if (currentTime < lrcData[i].tiem) {
            return i - 1 //返回歌词下标
        }
    }
    return lrcData.length - 1//如果找完了都还没有找的就返回最后一句歌词的下标
}

/**
 * 创建歌词元素
 */
function createElement() {
    for (let i = 0; i < lrcData.length; i++) {
        let li = document.createElement('li')//创建li标签
        li.textContent = lrcData[i].words//往li标签里面添加内容
        doms.ul.appendChild(li)//把li标签添加到ul标签下
    }
}
createElement()

/**
 * 设置当前播放时间ul元素的偏移量
 */
let containerHeight = doms.container.clientHeight//获取容器高度
let ulHeight = doms.ul.clientHeight//获取ul高度
let liHeight = doms.ul.children[0].clientHeight//获取单个li高度
let maxOffset = ulHeight - containerHeight//偏移最大高度
function setOffset() {
    let offset = findIndex() * liHeight + liHeight / 2 - containerHeight / 2 //偏移量
    if (offset < 0) {
        offset = 0//最小偏移量
    }
    if (offset > maxOffset) {
        offset = maxOffset//最大偏移量
    }
    
    doms.ul.style.transform = ` translateY(-${offset}px)`//设置偏移动画
    //去掉之前的样式
    var li = doms.ul.querySelector('.active');//获取所有带active类名的的节点赋值给li
    if (li) {
        li.classList.remove('active')//移除active
    }
    //添加新样式
    li = doms.ul.children[findIndex()]//获取当前播放元素赋值给li
    if (li) {
        li.classList.add('active')//给当前li添加active激活样式
    }
}
/**
 * 添加交互事件timeupdate播放位置改变时触发
 */
doms.audio.addEventListener("timeupdate", setOffset)

6.效果图

html5 歌词单击 歌词滚动的html代码_css_07