当前位置:首页 > JavaScript

js实现歌词同步

2026-01-30 13:40:24JavaScript

实现歌词同步的基本思路

歌词同步的核心是通过音频播放时间与歌词时间戳匹配,动态高亮当前播放的歌词行。需要将歌词文本解析为结构化数据(时间+文本),监听音频时间变化并更新UI。

歌词解析

歌词通常以LRC格式存储,每行格式为[mm:ss.xx]歌词文本。解析示例:

js实现歌词同步

function parseLRC(lrcText) {
  const lines = lrcText.split('\n');
  return lines.map(line => {
    const timeMatch = line.match(/^\[(\d{2}):(\d{2})\.(\d{2})\]/);
    if (!timeMatch) return null;

    const min = parseInt(timeMatch[1]);
    const sec = parseInt(timeMatch[2]);
    const centisec = parseInt(timeMatch[3]);
    const time = min * 60 + sec + centisec * 0.01;

    return {
      time,
      text: line.replace(timeMatch[0], '').trim()
    };
  }).filter(item => item);
}

同步逻辑实现

创建歌词同步控制器类,处理时间比对与UI更新:

js实现歌词同步

class LyricSync {
  constructor(lrcData, audioElement) {
    this.lrcArray = lrcData;
    this.audio = audioElement;
    this.currentIndex = 0;
    this.domElements = [];
  }

  init(container) {
    this.lrcArray.forEach((item, index) => {
      const div = document.createElement('div');
      div.textContent = item.text;
      div.dataset.index = index;
      container.appendChild(div);
      this.domElements.push(div);
    });
  }

  update() {
    const currentTime = this.audio.currentTime;

    // 查找当前应高亮的歌词行
    let activeIndex = this.lrcArray.findIndex(
      (item, idx) => currentTime < this.lrcArray[idx + 1]?.time || idx === this.lrcArray.length - 1
    );

    if (activeIndex !== -1 && activeIndex !== this.currentIndex) {
      this.domElements[this.currentIndex]?.classList.remove('active');
      this.currentIndex = activeIndex;
      this.domElements[this.currentIndex]?.classList.add('active');
      this.scrollToCurrent();
    }
  }

  scrollToCurrent() {
    const element = this.domElements[this.currentIndex];
    element?.scrollIntoView({ behavior: 'smooth', block: 'center' });
  }
}

使用示例

// 假设已有音频元素和歌词容器
const audio = document.getElementById('audio');
const lrcContainer = document.getElementById('lyrics');
const lrcText = `[00:01.00]第一行歌词\n[00:05.30]第二行歌词\n[00:10.20]第三行歌词`;

// 初始化
const parsedLRC = parseLRC(lrcText);
const lyricSync = new LyricSync(parsedLRC, audio);
lyricSync.init(lrcContainer);

// 添加时间更新监听
audio.addEventListener('timeupdate', () => lyricSync.update());

样式增强建议

为高亮当前歌词添加CSS样式:

#lyrics div {
  padding: 8px;
  transition: all 0.3s;
}
#lyrics div.active {
  color: #ff0000;
  font-size: 1.2em;
  font-weight: bold;
}

性能优化方向

对于长歌词列表,可采用虚拟滚动技术减少DOM节点数量。监听时间更新时使用requestAnimationFrame节流:

let isUpdating = false;
audio.addEventListener('timeupdate', () => {
  if (!isUpdating) {
    requestAnimationFrame(() => {
      lyricSync.update();
      isUpdating = false;
    });
    isUpdating = true;
  }
});

标签: 歌词同步js
分享给朋友:

相关文章

js实现图片轮播

js实现图片轮播

实现基础图片轮播 使用HTML、CSS和JavaScript创建一个简单的图片轮播。HTML部分定义轮播容器和图片,CSS设置样式和动画效果,JavaScript处理轮播逻辑。 <div cl…

js实现复制功能

js实现复制功能

使用 document.execCommand 方法 这种方法适用于较旧的浏览器,但在现代浏览器中可能被逐步淘汰。通过创建一个临时的 textarea 元素,将文本内容放入其中,然后执行复制命令。…

js实现列表

js实现列表

使用 JavaScript 实现列表 JavaScript 提供了多种方式来实现列表功能,包括数组操作、DOM 元素动态生成等。以下是几种常见的实现方法: 使用数组存储列表数据 数组是 JavaSc…

js防抖和节流实现

js防抖和节流实现

防抖(Debounce)的实现 防抖的核心思想是在事件被触发后,延迟执行回调函数。如果在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口大小调整等场景。 function debounce…

js实现防洪

js实现防洪

防抖(Debounce)实现 防抖的核心思想是在事件触发后延迟执行回调函数,若在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口调整等场景。 function debounce(func,…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: functio…