网页版音频播放器,歌词随音乐而动

2023-11-06

制作不易,多多支持,谢谢!!

我的博客里面还有关于视频播放器的,感兴趣的小伙伴可以来看看。

这个是效果图 

 这是利用audio做的一个歌词随音乐而动的html页面。


这个简单的音频播放器是用ajax请求本地服务器的lrc文件,lrc文件就是歌词文件。

歌词滚动的基本思想

把歌词放在盒子里面,通过audio的timeupdata事件监听音乐的播放,并获取当前播放的时间currentTime,然后通过当前播放的时间于歌词的时间匹配,匹配到的话就把歌词盒子往上移动。

第一步:通过ajax获取本地歌词

//用ajax请求数据
	function createXHR(){
		if(typeof(XMLHttpRequest)!='undefined'){
			return new XMLHttpRequest;
		}else if(typeof(ActiveXObject)!='undefined'){
			var xhrArr=['Microsoft.XMLHTTP','MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP.2.0'];
			var len=xhrArr.length,xhr;
			for(var i=0;i<length;i++){
				try{
					xhr=new ActiveXObject(xhrArr[i]);
					break;
				}catch(ex){
					
				}
				return xhr;
			}
		}else{
			throw new Error('no XHR')
		}
	}
	//创建XMLHttpRequest对象
	var xhr=createXHR(),data=null;
	//创建HTTP请求
	xhr.open('get','mz.lrc');
	//发送请求
	xhr.send(null);
	//响应XMLHttpRequest对象状态变化的函数,onreadystatechange在readystatechange属性发生改变时触发
	xhr.onreadystatechange=function(){
		//异步调用成功,相应内容解析完成,可在客户端调用
		if(xhr.readyState===4){
			if((xhr.status>=200&&xhr.status<300)||xhr.status==304){//304表示请求资源没有被修改,可以使用缓存
				//获得服务器返回数据
				data=xhr.responseText;
				//渲染数据到页面中
				renderDataToDom(data);
			}
		}
	}

 

第二部:处理歌词

歌词的格式是这样的

我们要转换的格式 

这里第108秒跑到了前面,所以我把时间排好序,又放到了一个数组中,用这个数组来滚动音乐。

 

 

function renderDataToDom(data){
		//将歌词中的时间格式转换成多少秒
		var pattern=/\[(\d{2}):(\d{2})\.(\d{2})\](.*)/g;
		var result=pattern.exec(data);
		while(result!=null){
			var time=parseInt(result[1])*60+parseInt(result[2])+parseFloat('0.'+result[3]);
			if(result[4]){
				lrcObj[time]=result[4];
			}
			result=pattern.exec(data);
		}
		//转换后的格式,有的顺序可能不对,转换顺序按从小到大
		var i=0;
		var fragment=document.createDocumentFragment();
		var li=null,sortObj={};
		for(var key in lrcObj){
			keysArr[i]=parseFloat(key);
			i++;
		}
		keysArr.sort((a,b)=>a-b);
		for(var i=0;i<keysArr.length;i++){
			sortObj[keysArr[i]]=lrcObj[keysArr[i]];
/*			console.log(''+keysArr[i]+lrcObj[keysArr[i]]);*/
			li=document.createElement("li");
			li.appendChild(document.createTextNode(sortObj[keysArr[i]]));
			fragment.appendChild(li);
		}
		//sortObj虽然是排完序后的对象,但顺序还是和之前一样,所以在排序的时候就把li加载好,匹配歌词的时候用时间来就行了。
		//将歌词添加到lyricsBox中
		lyricsBox.appendChild(fragment);
		//var len=Object.keys(lrcObj).length;//获取这个对象的长度
	}

第三步、创建audio对象,实现歌词随音乐而动

//创建audio对象
	var audio=new Audio;
	var isPlay=false;
	var nowTime;
	audio.src='芒种.mp3';
	audio.loop=true;
	audioPlay();
	function audioPlay(){
		//播放、暂停
		var play=document.getElementsByClassName('play')[0];
		console.log(keysArr);
		play.onclick=function(){
			if(isPlay){
				this.style.backgroundImage='url("img/pause.png")';
				isPlay=false;
				audio.pause();
			}else{
				this.style.backgroundImage='url("img/play.png")';
				isPlay=true;
				audio.play();
			}
			
		}
	}
	//歌词虽页面而动
	var m=0;//第几句,贯穿全剧
	var preTime=0;
	audio.ontimeupdate=function(){
		nowTime=this.currentTime;
		nowTime=parseFloat(nowTime.toFixed(2));	
		console.log(nowTime);
		console.log(preTime);
		//检测是否一首歌播放完
		if(nowTime<preTime){
			document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m-1].style.color='#fff';
			document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m-1].style.fontSize='18px';
			console.log(1111);
			m=0;
			preTime=0;
		}else{
			preTime=nowTime;
		}
		if(nowTime>=(keysArr[m]-0.25)){
			console.log(typeof(keysArr[m]))
			if(m>=1){
				document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m].previousElementSibling.style.color='#fff';
				document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m].previousElementSibling.style.fontSize='18px';
			}
			document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m].style.color='red';
			document.getElementsByClassName('lyricsBox')[0].children[0].children[0].children[m].style.fontSize='22px';
			m++;
			document.getElementsByClassName('lyricsBox')[0].children[0].style.top=-33*(m-4)+'px';	
		}
		
	}

    这里让当前的时间和之前做的时间数组匹配用了一个方法,先声明一个全局变量,并赋值为0,作为记录播放到第几局的一个变量,同时也是时间数组的下标,因为时间数组里面,下边就是第几句,对应的值就是第几句播放时的时间,当现在的时间大于时间数组的时间的时候,让该句歌词颜色变红并且字体变大,然后m++,然后让歌词盒子向上移动一个li的高度。这里歌词盒子有个初始top,这样做为了让当前的歌词显示在屏幕的中间。

   当前歌词变完色的同时,上一句歌词还要变回原样,所以在上面那一步操作之前,还要把当前m对应的歌词样式变回原样,还要注意的是这个m要大于一。

遇到的问题及解决

解决循环(loop)为true的时候,onended这个事件是不能用的问题

   还有就是,当循环(loop)为true的时候,onended这个事件是不能用的,所以我加了一个if语句,来判断这首歌是否播放完。做法就是,声明一个pretime的变量,赋初值为0,意思就是当前timeupdata时间监听的currentTime的上一个currentTime,比较preTime和currentTime,正常情况下currentTime是肯定大于preTime的,但当第一次播放结束时currentTime是小于preTime的,所以就用这个来判断音乐的循环播放。

如果在子盒子上加个margin-top,这个属性会作用到父盒子上,解决方法就是给子盒子加个边框

获取音频的currentTime属性,其实得到的是一个字符串,在比较的时候不知道这个问题,每次在判断是否播放完的时候的第十秒就出错了,然后把它转换成数字就行了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网页版音频播放器,歌词随音乐而动 的相关文章

随机推荐

  • 剑指 Offer II 075. 数组相对排序

    问题描述 给定两个数组 arr1 和 arr2 arr2 中的元素各不相同 arr2 中的每个元素都出现在 arr1 中 对 arr1 中的元素进行排序 使 arr1 中项的相对顺序和 arr2 中的相对顺序相同 未在 arr2 中出现过的
  • Linux下C++开发笔记--g++命令

    目录 1 前言 2 开发环境搭建 3 g 重要编译参数 4 实例 1 前言 最近学习在linux环境下进行C 开发的基础知识 参考的教程是基于VSCode和CMake实现C C 开发 Linux篇 非常适合小白入门学习 2 开发环境搭建 安
  • 医用电气设备和医疗器械区别?(GB9706)基本安全和基本性能?解读

    目录 一 医用电气设备的定义 二 医用电气设备的标准架构 三 国标 行标和国际标准 1 基本安全和基本性能的通用要求 2 并列要求 电磁兼容EMC 四 关于基本性能 Essential Performance 解读 1 何时引入基本性能 2
  • VMware Workstation 开启虚拟机后蓝屏

    VMware Workstation 开启虚拟机后主机蓝屏 注意 不用重装系统 不用重装系统 不用重装系统 版本 VMware Workstation Pro 15 5 0 出问题时的虚拟机 ubuntu 19 10 出问题后 开启其他虚拟
  • C语言快速排序算法

    今天要分享的是快速排序 快速排序的原理 用一个flag记录数组里面的一个值 一般是第一个 定义left为第一个元素的下标 right为最后一个元素的下标 从最后一个元素开始与flag比较 如果比flag大 那就right 否则arr lef
  • ADS1_2,JLINK,GIVEIO的安装

    ADS1 2 JLINK GIVEIO的安装 1 ADS1 2 2 JLINK 3 GIVEIO 4 使用 1 ADS1 2 由于老师发的是1 2版本 在win10上太老旧 网上步骤很零碎 所以找到大佬的帖子 如何在win10 安装ADS1
  • failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED

    电脑cudn版本12 机器学习框架要求cudn版本11 最初因为提示缺少对应的文件 缺少cublas64 11 dll cublasLt64 11 dll等等文件 然后把对应的cublas64 12 dll cublasLt64 12 dl
  • torchtext默认安装版本太低的原因及解决

    本文使用conda管理包 如果你使用pip 需要手动改变一下指令 问题 最近安装torchtext 老是给我安装成0 6版本 这个史前版本很多函数接口都是老的 甚至文档都找不到了 使用的安装指令如下 导致失败的安装指令 conda inst
  • ICCV 2023

    导读 TL DR 本文提出了一种新的置换自注意力 PSA 用于图像超分辨率任务 可以在保持计算成本较低的同时 处理大窗口自注意力 并基于PSA构建了一个新的超分辨率网络 SRFormer 在各项基准测试中取得了最先进的性能 先简单介绍一下图
  • OpenAI时却提示“OpenAI‘s services are not available in your country”

    OpenAI的官网址如下 https openai com blog chatgpt 进入官网后点击下图中红框中的按钮 进入注册页面 上面这句提示的英文很简单 翻译过来 就是OpenAI不允许中国用户使用 那OpenAI允许哪些国家的用户使
  • 用C语言求平均数的四种方法

    1 常规操作 两个数的平均数等于两数之和除以二 int main int a 10 int b 5 int c a b printf d n c system pause return 0 这种方法有一定的缺陷 当a或b的值够大时 以至于超
  • vim编辑器格式化代码

    他丫儿的搞啥子嘛 乱七八糟的 在vim中其实也有像Eclipse中的ctrl shift F 的自动格式化代码的操作 尽管非常强大 但是通常会破坏代码的原有的缩进 所以不建议在python这样缩进代替括号的语言中和源程序已经缩进过的代码中使
  • rabbitMQ 概念及特点

    Solr rabbitMQ rabbitMQ 特点 可靠性 Reliability RabbitMQ 使用一些机制来保证可靠性 如持久化 传输确认 发布确认 灵活的路由 Flexible Routing 在消息进入队列之前 通过 Excha
  • 【ONNX】使用 C++ 调用 ONNX 格式的 PyTorch 深度学习模型进行预测(Windows, C++, PyTorch, ONNX, Visual Studio, OpenCV)

    文章目录 1 安装依赖 2 导出 ONNX 格式的 PyTorch 模型 3 安装 Windows 平台 OpenCV 4 C 下 OpenCV 接口调用 ONNX 模型 1 安装依赖 要使用 ONNX 模型进行预测 就需要使用 onnx
  • C# 当前不会命中断点(调试时不能进入断点)

    相信大家都会遇到这个问题的 而且在我的项目经验中 发生主这个问题的原因特别多 本文把我遇到过的情况都记录下 供大家参考 1 运行调试时模式不对 应该选Debug才能进入断点 如果选择Release是不能的 注意项目属性里的配置也选择成Deb
  • java的背景

    要想学好一门语言 首先得了解这门语言的有什么用 优缺点是什么 才能更好的理解运用 所以 我在此介绍java的基础简介 1 java是以javaee后台开发 java web前台界面构成的体系结构 2 java的优点有 java的平台无关性
  • 用java实现打印功能

    用java实现打印 java awt中提供了一些打印的API 要实现打印 首先要获得打印对象 然后继承Printable实现接口方法print 以便打印机进行打印 最后用用Graphics2D直接输出直接输出 下面代码实现了简单的打印功能
  • android自动点击的实现流程记录

    一个android下自动点击触屏的程序 类似于windows下的按键精灵 自动帮我玩捕鱼达人 目标 用户可以通过配置脚本文件 自定义一系列的操作 例如 点击 长按 拖动 延时 颜色判断 循环 然后用音量 键启动 关闭脚本 思路 1 linu
  • PSO粒子群算法优化BP神经网络(PSO-BPNN)回归预测MATLAB代码

    PSO粒子群算法优化BP神经网络 PSO BPNN 回归预测MATLAB代码 有优化前后的对比 代码注释清楚 main为运行主程序 可以读取本地EXCEL数据 也可以加载本地数据 mat 使用换自己数据集 很方便 容易上手 以电厂运行数据为
  • 网页版音频播放器,歌词随音乐而动

    制作不易 多多支持 谢谢 我的博客里面还有关于视频播放器的 感兴趣的小伙伴可以来看看 这个是效果图 这是利用audio做的一个歌词随音乐而动的html页面 这个简单的音频播放器是用ajax请求本地服务器的lrc文件 lrc文件就是歌词文件