当前位置:首页 > 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结构创建轮播容器和图片元素: <div class="carousel"> <div class="carousel-inner">…

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 使用JavaScript实现拖拽功能需要监听鼠标事件,包括mousedown、mousemove和mouseup。以下是实现的基本逻辑: const draggableEleme…

js实现分页

js实现分页

实现分页的基本思路 分页功能通常需要处理数据分割、页码生成和用户交互。核心逻辑包括计算总页数、根据当前页截取数据、渲染页码按钮等。 前端分页实现(静态数据) 假设已有全部数据,仅需前端分页展示:…

js 进度条的实现

js 进度条的实现

使用 HTML 和 CSS 创建基础进度条 HTML 结构可以简单使用一个 div 元素作为容器,内部嵌套另一个 div 表示进度: <div class="progress-containe…

js如何实现继承

js如何实现继承

原型链继承 通过将子类的原型指向父类的实例实现继承。子类实例能够访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Parent…

js实现pdf在线预览

js实现pdf在线预览

使用PDF.js实现PDF在线预览 PDF.js是由Mozilla开发的一个开源JavaScript库,可以在网页中直接渲染PDF文件。以下是实现PDF在线预览的步骤: 引入PDF.js库 在HT…