首页 > 其他分享 >鸿蒙NEXT实战教程—实现音乐歌词同步滚动

鸿蒙NEXT实战教程—实现音乐歌词同步滚动

时间:2024-12-14 09:36:22浏览次数:4  
标签:教程 context 鸿蒙 歌词 00 NEXT let words lyric

之前写过一个音乐播放器项目,今天再给它完善一下,加一个歌词同步滚动。

没错,这就是幽蓝君被女大欺骗做的项目,往事不堪回首,一把辛酸泪。

幽蓝君的原则是,宁愿免费分享,也不卖给坏人。

先看效果图:

 

图片

 

要做歌词同步滚动,我们首先需要的文件资源就是音乐文件和与之匹配的歌词文件。现在歌词文件不太好找,没关系,我们可以自己做。先来看本项目的歌词示例,文件格式是.lrc

[00:20.5]   
[00:20.5]I walked through the door with you
[00:23.63]曾与你一起穿过那扇门
[00:23.63]The air was cold
[00:25.83]空气充满寒意
[00:25.83]But something 'bout it felt like home somehow and I
[00:31.41]不知为何却让我觉得温暖得像家一般
[00:31.41]Left my scarf there at your sister's house
[00:35.22]我把自己的围巾落在了你姐姐家

内容中除了要有歌词文本之外,还要有每一行歌词出现的时间点,大家按照这种格式创建就可以,就是一行一行写比较麻烦。

准备好之后把音乐和歌词放入rawfile文件夹中,播放音乐就不说了,我们今天只说歌词部分。

首先读取一下本地文件:

this.context .resourceManager.getRawFileContent('AllTooWell.lrc')  .then((value: Uint8Array) => {      
  let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });      
    let stringData = textDecoder.decodeWithStream(value, { stream: false });      
    this.mLrcEntryList = parseLrcLyric(stringData);  
  })

然后后要把歌词和时间分离出来分别存储,方便进行滚动展示,这里使用正则表达式来提取时间部分:

const lrcLineRegex: RegExp = new RegExp('\\[\\d{2,}:\\d{2}((\\.|:)\\d{2,})\\]', 'g');
for (let i = 0; i < lyric.length; i++) {  
    let lineTime = lyric[i].match(lrcLineRegex);  
     let lineText = lyric[i].replace(lrcLineRegex, '');  
     if (lineTime && lineText) {    
       for (let j = 0; j < lineTime.length; j++) {      
         let min = Number(String(lineTime[j].match(lrcTimeRegex1)).slice(1));      
         let sec = Number.parseFloat(String(lineTime[j].match(lrcTimeRegex2)));      
         let timeInSeconds = (min * 60 + sec) * 1000;      
         lrc.push({ lineStartTime: timeInSeconds, lineDuration: 0, lineWords: lineText, words: [] });    
       }  
   }}

这样就得到了一个由时间和内容组成的数组。

接下来将歌词逐行展示,这里使用的是绘制画布的方式:

for (let i = 0; i < lyric.words.length; i++) {  let wordStartTime = lyric.lineStartTime + lyric.words[i].wordStartTime;  let wordEndTime = lyric.lineStartTime + lyric.words[i].wordStartTime + lyric.words[i].duration;  if (wordStartTime <= this.lyricMilliSecondsTime && wordEndTime >= this.lyricMilliSecondsTime) {    let wordProgress =      (this.lyricMilliSecondsTime - wordStartTime) / lyric.words[i].duration / lyric.words.length;    let wordPassedProgress = i / lyric.words.length;    let progress = wordPassedProgress + wordProgress;    this.context.fillStyle = this.progressGrad(startX, gradY, endX, gradY, progress);    this.context.font =      this.fontWeight + ' ' + (this.mCurrentTextSize + this.TEXT_ADD_SIZE) + 'vp ' + this.fontFamily;    this.context.fillText(lyric.words[i].text, wordX, this.lrcY + this.TEXT_ADD_SIZE / 2, this.lrcWidth);  } else {    this.context.font = this.fontWeight + ' ' + this.mCurrentTextSize + 'vp ' + this.fontFamily;    this.context.fillText(lyric.words[i].text, wordX, this.lrcY, this.lrcWidth);  }  wordX += this.context.measureText(lyric.words[i].text).width;}

下面就是歌词同步滚动的问题,在播放音乐的时候肯定会有一个计时器,歌词滚动同样使用这个计时器,计时器计数改变时,找到对应的歌词,并计算该行歌词的行数和偏移量,进行画布滚动,就可以实现歌词的同步滚动了,我们还可以对歌词的透明度进行绘制,实现渐隐渐出的效果。

由于众所周知的原因,本项目就和大家分享一个大概的思路,有了思路这个功能就不是很难了,感谢您的阅读。

标签:教程,context,鸿蒙,歌词,00,NEXT,let,words,lyric
From: https://www.cnblogs.com/youlanjihua/p/18606350

相关文章

  • 鸿蒙开发中console.log和hilog的区别
    在日常开发中打印日志是调试程序非常常用的操作,在鸿蒙的官方文档中介绍了hilog这种方式,有些前端转过来的友友发现console.log也可以进行日志打印。有一段时候幽蓝君也非常喜欢使用console.log,因为它看起来好像更加简单方便。那么今天幽蓝君就来和大家说一说console.log和hilog有......
  • HarmonyOS NEXT开发实战教程—淘宝搜索页
    今天忙里偷闲,分享一个淘宝搜索页实现过程,先上效果图:  界面部分比较简单,大体分为导航栏、历史搜索、猜你想搜和热搜榜几个部分,历史搜索采用用户首选项进行存储数据。导航栏部分相关代码如下:Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap,alignItems:ItemAlign.......
  • 码支付支付宝免挂手动配置通道详细教程
    码支付地址码支付-码支付官网(pay.yizhifu.top)-三网免挂码支付,码支付授权官网,聚合支付,易支付官网,源支付,即时到账支付接口,免签约支付,虎皮椒支付码支付官网(pay.yizhifu.top)是集成微信支付、支付宝支付、QQ钱包支付等多场景聚合支付接口的平台,保障每位商户资金即时到账;解决个人开......
  • 在CodeBolcks+Windows API下的C++编程教程——给你的项目中添加头文件和菜单
    0.前言我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”:学习编程......
  • 剪映破解版、剪映 VIP 版本下载安装教程,亲测有效
    大家好!今天要给各位小伙伴们安利一款我亲测超好用的视频剪辑工具——剪映!更劲爆的是,这里推荐的还是剪映破解版——支持永久VIP功能,完全免费,真的爱不释手!对于我们这些天天和视频打交道的UP主来说,这简直是创作道路上的一盏明灯!链接地址:https://pan.quark.cn/s/ce0be681b9a5链......
  • 信息收集利器Shodan教程——Shodan(2)
    Shodan(2)批量查找并验证漏洞CVE-2019-0708原理存在漏洞的远程桌面服务器,在接收到特殊数据包时会释放一个内部信道MST120的控制结构体,但并未将指向该结构体的指针删除。内部信道:定义:内部信道通常指的是在一个设备、系统或网络内部用于信息传输的通道。分类:逻......
  • 五阶魔方教程
    初学五阶魔方首先,请先看过之前的四阶魔方教学,或者其它类似转法的网页,因为接下来的内容全是建立在魔方的概念上然后加以延伸。同样的,这个教学只介绍能够解出所需最容易的方法,并称不上非常有效率。 1.完成中心五阶是奇数层,中心是固定的,所以没有四阶中心定位错误的问题。拼中心......
  • 【中工开发者】鸿蒙——网络访问介绍
            本学期在校学习了鸿蒙开发课程,希望通过本篇文章总结一下鸿蒙的网络访问,为大家提供一些参考。一、概述        鸿蒙系统通过网络管理模块为用户提供了网络通信服务,支持以下主要通信方式:Socket通信:基于TCP和UDP协议,通过套接字(Socket)进行数据传......
  • 在CodeBolcks+Windows API下的C++编程教程——给你的项目中添加资源文件和图标
    0.前言我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”:学习编程......
  • php.ini 文件上传/执行时间/部分配置新手教程
    1、上传文件大小配置一般需要同时配置“upload_max_filesize”、“post_max_size”,配置格式如下:file_uploads=On;是否允许HTTP文件上传upload_max_filesize=2M;设置单个文件上传的最大尺寸post_max_size=8M;设置POST请求体的最大尺寸,包括所有表单数据2、脚本最......