当前位置:首页 > JavaScript

js实现歌词同步

2026-01-30 13:40:24JavaScript

实现歌词同步的基本思路

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

歌词解析

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

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更新:

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节流:

js实现歌词同步

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

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

相关文章

js实现轮播

js实现轮播

实现轮播图的基本思路 轮播图的核心逻辑是通过定时切换展示的图片或内容,通常结合左右滑动按钮和指示器(小圆点)增强交互性。以下是基于原生JavaScript的实现方法。 HTML结构 构建轮播图的HT…

js实现轮播图

js实现轮播图

基础轮播图实现 使用HTML、CSS和JavaScript实现一个简单的自动轮播图。HTML结构包含一个容器和多个图片项。 <div class="slider"> <div…

js防抖和节流实现

js防抖和节流实现

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

jquery js

jquery js

jQuery 简介 jQuery 是一个快速、简洁的 JavaScript 库,简化了 HTML 文档遍历、事件处理、动画和 Ajax 交互。它兼容多种浏览器,提供易于使用的 API,使开发者能够更高…

js实现祖玛

js实现祖玛

实现祖玛游戏的核心思路 祖玛游戏的核心玩法是发射彩色珠子,形成三个或以上相同颜色的珠子即可消除。以下是使用JavaScript实现的基本框架。 游戏初始化 创建画布并初始化游戏状态: const…

js实现自举

js实现自举

实现 JavaScript 自举的方法 JavaScript 自举(Bootstrap)通常指通过 JavaScript 动态加载自身或依赖的脚本,实现运行时环境的初始化或扩展。以下是几种常见实现方式…