当前位置:首页 > 前端开发 > 正文

html如何实现歌词滚动播放

HTML中,通过结合CSS和JavaScript,可以实现歌词滚动播放,使用“标签嵌入音频,利用JavaScript监听音频 播放时间,动态调整歌词列表的位置,并配合CSS实现平滑滚动效果

HTML中实现歌词滚动播放,需要结合HTML、CSS和JavaScript来完成,以下是详细的实现步骤和相关代码示例:

HTML结构搭建

创建一个基本的HTML结构,包含音频播放控件和用于显示歌词的容器。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">歌词滚动播放</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <audio id="audioPlayer" src="song.mp3" controls></audio>
    <div class="lyrics-container">
        <ul id="lyricsList"></ul>
    </div>
    <script src="script.js"></script>
</body>
</html>

CSS样式设计

使用CSS来设置歌词容器的样式,包括高度、溢出隐藏等,以及歌词列表项的样式。

body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    text-align: center;
}
.lyrics-container {
    width: 500px;
    height: 200px;
    margin: 20px auto;
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #fff;
}
#lyricsList {
    list-style: none;
    padding: 0;
    margin: 0;
    transition: transform 0.5s ease-in-out;
}
#lyricsList li {
    height: 30px;
    line-height: 30px;
    text-align: center;
}
.active {
    color: red;
    font-weight: bold;
}

JavaScript逻辑实现

JavaScript是实现歌词滚动播放的核心部分,主要负责解析歌词文件、同步音频播放进度、更新歌词显示等。

html如何实现歌词滚动播放  第1张

1 解析歌词文件

歌词文件采用LRC格式,包含时间戳和歌词内容,我们需要编写一个函数来解析这种格式的歌词文件。

function parseLrc(lrcText) {
    const lines = lrcText.split('n');
    const lyrics = [];
    lines.forEach(line => {
        const match = line.match(/[(d{2}):(d{2}).(d{2})](.+)/);
        if (match) {
            const minutes = parseInt(match[1], 10);
            const seconds = parseInt(match[2], 10);
            const milliseconds = parseInt(match[3], 10);
            const time = minutes  60 + seconds + milliseconds / 100;
            const word = match[4];
            lyrics.push({ time, word });
        }
    });
    return lyrics;
}

2 加载歌词文件

可以使用fetch API来异步加载歌词文件,并将其传递给解析函数。

fetch('lyrics.lrc')
    .then(response => response.text())
    .then(lrcText => {
        const lyrics = parseLrc(lrcText);
        renderLyrics(lyrics);
    })
    .catch(error => console.error('Error loading lyrics:', error));

3 渲染歌词到页面

将解析后的歌词数据动态生成到HTML列表中。

function renderLyrics(lyrics) {
    const lyricsList = document.getElementById('lyricsList');
    lyricsList.innerHTML = ''; // 清空现有列表
    lyrics.forEach(lyric => {
        const li = document.createElement('li');
        li.textContent = lyric.word;
        lyricsList.appendChild(li);
    });
}

4 同步音频播放与歌词高亮

通过监听音频的timeupdate事件,获取当前播放时间,并与歌词的时间戳进行比较,找到当前应该高亮的歌词项。

const audioPlayer = document.getElementById('audioPlayer');
let currentIndex = 0;
audioPlayer.addEventListener('timeupdate', () => {
    const currentTime = audioPlayer.currentTime;
    const lyrics = Array.from(document.querySelectorAll('#lyricsList li'));
    let found = false;
    for (let i = 0; i < lyrics.length; i++) {
        const lyricTime = lyrics[i].dataset.time;
        if (currentTime >= lyricTime) {
            currentIndex = i;
            found = true;
        } else {
            break;
        }
    }
    if (!found) {
        currentIndex = lyrics.length 1;
    }
    updateLyricsHighlight(currentIndex);
});

5 更新歌词高亮显示

根据当前索引,更新歌词列表项的高亮状态。

function updateLyricsHighlight(index) {
    const lyrics = document.querySelectorAll('#lyricsList li');
    lyrics.forEach((lyric, i) => {
        if (i === index) {
            lyric.classList.add('active');
        } else {
            lyric.classList.remove('active');
        }
    });
}

处理歌词滚动

当歌词列表项超过容器高度时,需要滚动歌词以保持当前歌词在可视区域内,可以通过调整transform属性来实现平滑滚动。

function scrollLyricsToCurrent() {
    const lyricsContainer = document.query.contains('.lyrics-container');
    const lyricsList = document.getElementById('lyricsList');
    const currentLyric = lyricsList.children[currentIndex];
    const containerHeight = lyricsContainer.clientHeight;
    const listItemHeight = currentLyric.clientHeight;
    const scrollOffset = currentLyric.offsetTop (containerHeight listItemHeight) / 2;
    lyricsList.style.transform = `translateY(-${scrollOffset}px)`;
}

updateLyricsHighlight函数中调用scrollLyricsToCurrent函数,确保每次高亮更新时都检查并调整滚动位置。

完整示例代码整合

将上述各部分代码整合在一起,形成一个完整的实现。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">歌词滚动播放</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            text-align: center;
        }
        .lyrics-container {
            width: 500px;
            height: 200px;
            margin: 20px auto;
            overflow: hidden;
            border: 1px solid #ccc;
            background-color: #fff;
        }
        #lyricsList {
            list-style: none;
            padding: 0;
            margin: 0;
            transition: transform 0.5s ease-in-out;
        }
        #lyricsList li {
            height: 30px;
            line-height: 30px;
            text-align: center;
        }
        .active {
            color: red;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <audio id="audioPlayer" src="song.mp3" controls></audio>
    <div class="lyrics-container">
        <ul id="lyricsList"></ul>
    </div>
    <script>
        function parseLrc(lrcText) {
            const lines = lrcText.split('n');
            const lyrics = [];
            lines.forEach(line => {
                const match = line.match(/[(d{2}):(d{2}).(d{2})](.+)/);
                if (match) {
                    const minutes = parseInt(match[1], 10);
                    const seconds = parseInt(match[2], 10);
                    const milliseconds = parseInt(match[3], 10);
                    const time = minutes  60 + seconds + milliseconds / 100;
                    const word = match[4];
                    lyrics.push({ time, word });
                }
            });
            return lyrics;
        }
        fetch('lyrics.lrc')
            .then(response => response.text())
            .then(lrcText => {
                const lyrics = parseLrc(lrcText);
                renderLyrics(lyrics);
            })
            .catch(error => console.error('Error loading lyrics:', error));
        function renderLyrics(lyrics) {
            const lyricsList = document.getElementById('lyricsList');
            lyricsList.innerHTML = ''; // 清空现有列表
            lyrics.forEach(lyric => {
                const li = document.createElement('li');
                li.textContent = lyric.word;
                li.dataset.time = lyric.time; // 存储时间戳以便后续使用
                lyricsList.appendChild(li);
            });
        }
        const audioPlayer = document.getElementById
0