来日方长

    document.addEventListener(‘DOMContentLoaded’, async function () { // 获取音频播放器元素 const audio = document.getElementById(‘audio-player’); // 获取歌词容器元素 const lyricsContainer = document.getElementById(‘lyrics’); // 获取歌词容器的父容器 const container = document.getElementById(‘lyrics-container’); // 歌词文件的URL const lyricsFile = ‘https://fanym.oss-cn-beijing.aliyuncs.com/wp-content/uploads/2024/11/%E8%96%9B%E4%B9%8B%E8%B0%A6%20_%20%E9%BB%84%E9%BE%84%20-%20%E6%9D%A5%E6%97%A5%E6%96%B9%E9%95%BF.lrc’; // 当前高亮的歌词索引 let currentIndex = 0; // 存储解析后的歌词数据 let lyrics = []; // 用户是否正在滚动歌词容器 let isUserScrolling = false; // 用于清除定时器 let scrollTimeout; // 从指定URL获取歌词文件内容 const lrcText = await fetchLyrics(lyricsFile); // 解析歌词文本 parseLRC(lrcText); function fetchLyrics(url) { return fetch(url).then(response => response.text()); } function parseLRC(lrcText) { // 将歌词文本按行分割 const lines = lrcText.split(‘\n’); // 解析每一行歌词的时间戳和文本 lyrics = lines.map(line => { const timeMatch = line.match(/\[(\d{2}):(\d{2})\.(\d{1,2})\]/); if (timeMatch) { const minutes = parseInt(timeMatch[1], 10); const seconds = parseInt(timeMatch[2], 10); const milliseconds = parseInt(timeMatch[3].padEnd(2, ‘0’), 10); const timeInSeconds = minutes * 60 + seconds + milliseconds / 100; const lyricText = line.replace(/\[.*?\]/g, ”).trim(); if (lyricText) return { time: timeInSeconds, text: lyricText }; } return null; }).filter(item => item !== null); // 渲染解析后的歌词 renderLyrics(); } function renderLyrics() { // 创建文档片段以批量插入DOM节点 const fragment = document.createDocumentFragment(); // 遍历歌词数组创建DOM节点 lyrics.forEach((lyric, index) => { const li = document.createElement(‘li’); li.textContent = lyric.text; if (lyric.time !== null) { li.dataset.time = lyric.time.toString(); // 绑定点击事件以跳转到指定时间点 li.addEventListener(‘click’, (event) => { const clickedLi = event.target; const clickedTime = parseFloat(clickedLi.dataset.time); audio.currentTime = clickedTime; const clickedIndex = Array.from(document.querySelectorAll(‘#lyrics li’)).indexOf(clickedLi); highlightLyric(clickedLi, clickedIndex); scrollToLyric(clickedIndex); // 如果当前点击行的时间戳与下一行相同,则认为下一行是翻译 if (clickedIndex { if (lyric.time && lyric.time = 0 && !isUserScrolling) { currentIndex = foundIndex; // 高亮当前行并滚动到该行 highlightLyric(lines[currentIndex], currentIndex); scrollToLyric(currentIndex); } } audio.addEventListener(‘timeupdate’, function () { // 在音频播放时更新当前时间对应的歌词显示 const currentTime = audio.currentTime; synchronizeLyricsWithAudio(currentTime); }); function highlightLyric(line, index) { // 移除所有行的高亮样式 document.querySelectorAll(‘#lyrics li’).forEach(li => { li.classList.remove(‘highlight’, ‘translation’); // 移除所有高亮样式 }); // 如果当前行时间戳与前一行相同,则当前行为译文,前一行为原文 if (index > 0) { const prevLine = document.querySelectorAll(‘#lyrics li’)[index – 1]; const prevTime = lyrics[index – 1].time; const currentTime = lyrics[index].time; if (prevTime === currentTime) { prevLine.classList.add(‘highlight’); // 前一行为原文,红色高亮 line.classList.add(‘translation’); // 当前行为译文,蓝色斜体 } else { // 如果时间戳不同,则当前行是原文 line.classList.add(‘highlight’); // 原文为红色高亮 } } else { // 如果是第一行,则直接高亮 line.classList.add(‘highlight’); // 原文为红色高亮 } } function scrollToLyric(index) { // 获取需要滚动到的行元素 const line = document.querySelectorAll(‘#lyrics li’)[index]; const offsetTop = line.offsetTop; const containerHeight = container.offsetHeight; const lineHeight = line.offsetHeight; const scrollTop = container.scrollTop; const scrollBottom = scrollTop + containerHeight; // 判断当前行是否已经在可视区域内 if (offsetTop scrollBottom) { // 如果超出可视区域则滚动到该行 if (container.scrollHeight > container.offsetHeight) { const scrollTarget = Math.max(0, offsetTop – containerHeight / 5 + lineHeight / 5); container.scrollTop = scrollTarget; } } } container.addEventListener(‘scroll’, function () { // 用户滚动歌词容器时设置标志位,并清除之前的定时器 isUserScrolling = true; clearTimeout(scrollTimeout); scrollTimeout = setTimeout(() => { isUserScrolling = false; }, 3000); }); }); #lyrics li { list-style: none; padding: 5px; color: #333; cursor: pointer; margin-bottom: 0; /* 去除行与行之间的额外空隙 */ line-height: 1.2; /* 调整行高,保持原文和译文紧密 */ } #lyrics li.highlight { color: #d9534f; /* 原文高亮为红色 */ font-weight: bold; font-size: 1.2em; background-color: rgba(255, 215, 0, 0.2); /* 原文高亮背景 */ } #lyrics li.translation { color: #337ab7; /* 译文为蓝色 */ font-style: italic; /* 译文使用斜体 */ margin-top: 0; /* 移除原文和译文之间的空隙 */ background-color: rgba(255, 215, 0, 0.2); /* 译文高亮背景 */ } #audio-player { width: 100%; } #lyrics-container { /* 添加平滑滚动 */ scroll-behavior: smooth; }

    评论

    4 + 9 = ?
    您的邮箱地址不会被公开。必填项已用 * 标注 如遇验证码无法通过,请勿使用无痕/隐私浏览器模式