HTML5使用Audio标签实现歌词同步的效果

下面是详细的攻略说明。

什么是HTML5的Audio标签?

HTML5的Audio标签是一种用于在网页上播放音频的标签。它可以加载并播放MP3、WAV等音频格式文件。除了简单的播放控制外,它还支持许多高级特性,例如事件处理、音乐可视化和歌词同步等。

实现歌词同步的原理

在实现歌词同步的过程中,我们需要先将歌词文件加载到网页中,并把每一行的歌词内容和对应的时间信息保存下来。然后我们需要监听音频播放的事件,根据当前音频播放的时间,找到对应的歌词并将其高亮显示出来。

具体地,我们可以使用timeupdate事件来监听音频播放时间的更新。每次事件触发时,我们需要根据当前的播放时间,找到对应的歌词并将其高亮显示出来。代码示例如下:

<audio id="myAudio" src="song.mp3"></audio>

<div id="lyrics">
  <p data-time="0">歌词第一行</p>
  <p data-time="10">歌词第二行</p>
  <p data-time="20">歌词第三行</p>
  <!-- 其他歌词行 -->
</div>

<script>
  var audio = document.getElementById('myAudio');
  var lyricsElement = document.getElementById('lyrics');
  var lyrics = lyricsElement.getElementsByTagName('p');
  var currentLyricIndex = -1;

  audio.addEventListener('timeupdate', function() {
    var currentTime = audio.currentTime;

    // 找到歌词所在行
    for (var i = lyrics.length - 1; i >= 0; i--) {
      if (lyrics[i].getAttribute('data-time') <= currentTime) {
        currentLyricIndex = i;
        break;
      }
    }

    // 高亮显示歌词
    for (var i = 0; i < lyrics.length; i++) {
      if (i === currentLyricIndex) {
        lyrics[i].classList.add('active');
      } else {
        lyrics[i].classList.remove('active');
      }
    }
  });
</script>

示例一:歌词滚动实现

除了高亮显示当前歌词外,我们还可以实现歌词滚动的效果,让用户更方便地看到当前唱到了哪一句歌词。具体实现方法是在当前歌词的基础上,再找到前后一句歌词以及它们所对应的时间,然后根据当前播放时间和这三个时间的差值来计算出歌词应该滚动的距离。代码示例如下:

<audio id="myAudio" src="song.mp3"></audio>

<div id="lyrics">
  <p data-time="0">歌词第一行</p>
  <p data-time="10">歌词第二行</p>
  <p data-time="20">歌词第三行</p>
  <!-- 其他歌词行 -->
</div>

<script>
  var audio = document.getElementById('myAudio');
  var lyricsElement = document.getElementById('lyrics');
  var lyrics = lyricsElement.getElementsByTagName('p');
  var currentLyricIndex = -1;

  audio.addEventListener('timeupdate', function() {
    var currentTime = audio.currentTime;

    // 找到当前歌词和前后一句歌词,以及它们所对应的时间
    var currentLyric = null;
    var previousLyric = null;
    var nextLyric = null;
    var currentLyricTime = 0;
    var previousLyricTime = 0;
    var nextLyricTime = Number.MAX_VALUE;
    for (var i = lyrics.length - 1; i >= 0; i--) {
      var lyricTime = parseFloat(lyrics[i].getAttribute('data-time'));
      if (lyricTime <= currentTime) {
        currentLyric = lyrics[i];
        currentLyricTime = lyricTime;
        break;
      } else {
        nextLyric = lyrics[i];
        nextLyricTime = lyricTime;
      }
    }
    for (var i = 0; i < lyrics.length; i++) {
      var lyricTime = parseFloat(lyrics[i].getAttribute('data-time'));
      if (lyricTime < currentLyricTime && lyricTime > previousLyricTime) {
        previousLyric = lyrics[i];
        previousLyricTime = lyricTime;
      }
      if (lyricTime > currentLyricTime && lyricTime < nextLyricTime) {
        nextLyric = lyrics[i];
        nextLyricTime = lyricTime;
      }
    }

    // 高亮显示当前歌词
    for (var i = 0; i < lyrics.length; i++) {
      if (i === currentLyricIndex) {
        lyrics[i].classList.add('active');
      } else {
        lyrics[i].classList.remove('active');
      }
    }

    // 计算歌词滚动的距离
    if (currentLyric) {
      var scrollDistance = 0;
      var lineHeight = parseFloat(getComputedStyle(currentLyric).lineHeight);
      var currentLineTop = currentLyric.offsetTop - lyricsElement.offsetTop;
      var previousLineTop = previousLyric ? previousLyric.offsetTop - lyricsElement.offsetTop : currentLineTop - lineHeight;
      var nextLineTop = nextLyric ? nextLyric.offsetTop - lyricsElement.offsetTop : currentLineTop + lineHeight;
      var currentLineTime = currentLyricTime;
      var previousLineTime = previousLyricTime ? previousLyricTime : currentLyricTime - 1;
      var nextLineTime = nextLyricTime;
      var progress = (currentTime - currentLineTime) / (nextLineTime - currentLineTime);
      scrollDistance = (nextLineTop - currentLineTop) * progress + currentLineTop - lyricsElement.offsetHeight / 2 + lineHeight / 2;

      lyricsElement.scrollTop = scrollDistance;
    }
  });
</script>

示例二:根据歌曲进度显示歌词

除了根据音频的播放时间来显示歌词,我们还可以根据歌曲的进度来显示歌词。具体实现方法是在加载歌曲时,计算出每个歌词所对应的时间点,并将其保存在一个数组中。然后在歌曲播放的过程中,根据当前的进度找到对应的歌词并显示出来。代码示例如下:

<audio id="myAudio" src="song.mp3"></audio>

<div id="lyrics">
  <!-- 歌词行 -->
</div>

<script>
  var audio = document.getElementById('myAudio');
  var lyricsElement = document.getElementById('lyrics');
  var lyrics = lyricsElement.getElementsByTagName('p');
  var lyricTimes = [];
  var currentLyricIndex = -1;

  // 加载歌词并计算每个歌词所对应的时间点
  function loadLyrics(lyricsUrl) {
    fetch(lyricsUrl)
      .then(function(response) {
        return response.text();
      })
      .then(function(text) {
        var lines = text.split('\n');
        for (var i = 0; i < lines.length; i++) {
          var match = lines[i].match(/^\[(\d+):(\d+\.\d+)\](.*)$/);
          if (match) {
            var minutes = parseInt(match[1]);
            var seconds = parseFloat(match[2]);
            var time = minutes * 60 + seconds;
            var content = match[3];
            lyricsElement.innerHTML += '<p data-time="' + time + '">' + content + '</p>';
            lyricTimes.push(time);
          }
        }
      });
  }

  // 在歌曲播放的过程中,根据当前的进度找到对应的歌词并显示出来
  audio.addEventListener('timeupdate', function() {
    var currentTime = audio.currentTime;
    for (var i = 0; i < lyricTimes.length; i++) {
      if (lyricTimes[i] > currentTime) {
        if (currentLyricIndex !== i - 1) {
          for (var j = 0; j < lyrics.length; j++) {
            if (j === i - 1) {
              lyrics[j].classList.add('active');
            } else {
              lyrics[j].classList.remove('active');
            }
          }
          currentLyricIndex = i - 1;
          break;
        }
      }
    }
  });

  // 加载歌曲和歌词
  loadLyrics('song.lrc');
</script>

以上是使用HTML5的Audio标签实现歌词同步的完整攻略。在实际开发中,我们可以根据需要进行修改和优化,以达到更好的效果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:HTML5使用Audio标签实现歌词同步的效果 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 从几个方面聊聊页面重构中的一些问题

    本文将从以下几个方面详细讲解页面重构中的一些问题: 什么是页面重构? 为什么要进行页面重构? 页面重构的注意事项 页面重构的实践示例 什么是页面重构? 页面重构可以理解为将已有的页面代码进行重新整理、修改和优化的过程。其目的是提高页面的代码质量、优化用户体验、增强页面的可访问性和SEO(搜索引擎优化)效果等。 重构的具体方式可以是对HTML/CSS/JS等静…

    css 2023年6月11日
    00
  • 网页切图的CSS和布局经验与要点

    网页切图的CSS和布局经验与要点 在进行网页切图时,CSS和布局经验是非常重要的一部分。下面将详细讲解几个要点: 1. 掌握盒子模型 盒子模型指的是一个HTML元素的大小和位置,由元素的内容(content)、内边距(padding)、边框(border)和外边距(margin)组成,它们按顺序从内到外围绕着元素。掌握盒子模型可以更好地控制整个页面的布局。 …

    css 2023年6月10日
    00
  • 高性能JavaScript 重排与重绘(2)

    高性能JavaScript 重排与重绘(2) 完整攻略 什么是重排与重绘 在了解高性能JavaScript中的重排(re-layout)和重绘(re-paint)之前,需要先了解一些页面绘制的基础知识。当我们访问一个网站时,浏览器会先对HTML进行解析,并生成DOM树。接着,CSS样式会被解析,并生成样式树。浏览器在解析文档的同时,还会对JavaScript…

    css 2023年6月10日
    00
  • css利用A标签的背景可能作出很有意思的效果

    针对这个问题,我可以给出以下完整攻略: CSS利用 A标签的背景 可以作出很有意思的效果 1. 利用 background-image 设置背景图片 可以通过 background-image 属性设置 A 标签的背景图片。通过精心的设计,可以为网站增添一些浪漫或者复古的气息,使得用户体验更加丰富多彩。 下面是一个设置背景图片的例子: a { backgro…

    css 2023年6月9日
    00
  • java中的快捷键小结

    我很愿意为您提供关于Java中的快捷键的完整攻略。下面是我的讲解: 什么是Java中的快捷键? 快捷键是指在编程过程中一些可以快速执行特定操作的快速键盘键组合。使用快捷键常常可以帮助程序员提高代码编写效率。而Java中也提供了一些常用的快捷键,接下来是针对Java里的快捷键做的一些整理和归纳。 Java中的快捷键列表 Ctrl + Shift + T 搜索类…

    css 2023年6月10日
    00
  • vue 框架下自定义滚动条(easyscroll)实现方法

    接下来我将为你详细讲解“Vue 框架下自定义滚动条(easyscroll)实现方法”的完整攻略。 1. 简介 当我们需要在 Vue 项目中使用自定义滚动条时,可以选择使用第三方库来实现,比如 Vuetify 的 v-scroll-x 或者 vue-bar 的 bar. 而在不使用任何第三方库的情况下,我们可以使用 easyscroll 插件,它是一个轻量级的…

    css 2023年6月10日
    00
  • 盘点五个惊艳一时的CSS属性(不常用但很有用)

    那么先来介绍一下所谓的“盘点五个惊艳一时的CSS属性(不常用但很有用)”吧。 什么是“盘点五个惊艳一时的CSS属性(不常用但很有用)”? 这篇文章提到的“五个惊艳一时的CSS属性”即包括如下五个: appearance:用于控制元素的默认外观 mix-blend-mode:用于控制元素混合模式 clip-path:用于裁剪元素的形状 backface-vis…

    css 2023年6月9日
    00
  • CSS中下拉菜单和表单以及弹出层的简单笔记

    当涉及到网站的用户体验时,下拉菜单、表单和弹出层是非常重要的元素。在CSS中,我们可以使用不同的技术和属性来创建这些元素。 下拉菜单 下拉菜单是一种常见的界面元素,它可以让用户轻松地选择选项。在HTML中,我们可以使用<select>元素创建下拉菜单。在CSS中,我们可以使用select选择器和伪类选择器来样式化下拉菜单。 样式化下拉菜单 要样式…

    css 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部