前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。
1、演示

2、代码分析
逐行解析 JavaScript 代码块:
const audioEle = document.querySelector('audio') const cvs = document.querySelector('canvas') const ctx = cvs.getContext('2d')这几行代码首先获取了
<audio>和<canvas>元素的引用,并使用getContext('2d')方法获取了 Canvas 2D 上下文对象,以便后续在画布上进行绘图操作。function initCvs() {cvs.width = window.innerWidth * devicePixelRatiocvs.height = (window.innerHeight / 2) * devicePixelRatio } initCvs()
initCvs函数用于初始化画布的尺寸。它将画布的宽度设置为窗口宽度的倍数,高度设置为窗口高度的一半,同时乘以设备像素比devicePixelRatio,以确保在不同设备上显示的效果一致。let isInit = false let dateArray = null let analyser = null这几行定义了一些状态变量,用于跟踪音频分析器的初始化状态、频率数据数组、分析器对象以及音频播放状态。
audioEle.addEventListener('play', function (e) {if (isInit) return// 初始化const audCtx = new AudioContext() // 创建音频上下文const source = audCtx.createMediaElementSource(audioEle) // 创建音频源节点analyser = audCtx.createAnalyser()analyser.fftSize = 512 // 设置 FFT 大小dateArray = new Uint8Array(analyser.frequencyBinCount) // 创建存储频率数据的数组source.connect(analyser)analyser.connect(audCtx.destination)isInit = true })这段代码是一个事件监听器,当音频开始播放时触发。在此事件处理程序中:
- 首先检查是否已经初始化过分析器,如果是,则直接返回。
- 创建 AudioContext 对象
audCtx,用于处理音频。- 使用
createMediaElementSource方法创建音频源节点source,将<audio>元素作为输入。- 创建 AnalyserNode 对象
analyser,用于分析音频频率数据。- 设置 AnalyserNode 的 fftSize 属性为 512,表示采样点数。
- 创建一个 Uint8Array 数组
dateArray用于存储频率数据。- 将音频源节点连接到分析器节点,然后将分析器节点连接到 AudioContext 的目标节点。
- 最后设置状态变量
isInit为 true,表示分析器已经初始化且音频正在播放。function draw() {requestAnimationFrame(draw)// 清空画布const { width, height } = cvsctx.clearRect(0, 0, width, height)if (!isInit && !isPlay) return// 获取频率数据并绘制波形图analyser.getByteFrequencyData(dateArray)const len = dateArray.length / 2.5ctx.fillStyle = '#266fff'const barWidth = width / len / 2for (let i = 0; i < len; i++) {const data = dateArray[i] // < 256const barHeight = (data / 255) * heightconst x1 = i * barWidth + width / 2const x2 = width / 2 - (i + 1) * barWidthconst y = height - barHeightctx.fillRect(x1, y, barWidth - 2, barHeight)ctx.fillRect(x2, y, barWidth - 2, barHeight)} } draw()
draw函数用于绘制波形图,通过requestAnimationFrame实现动画效果。在函数中:
- 首先清空画布。
- 检查分析器是否已初始化并且音频正在播放,如果不是,则直接返回。
- 使用
analyser.getByteFrequencyData方法获取频率数据,并存储在dateArray中。- 计算每个柱状条的宽度和高度,并根据频率数据绘制柱状图形。
3、全部代码
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>body {background-color: #ffffff;display: flex;justify-content: center;align-items: center;flex-direction: column;}* {margin: 0;padding: 0;}canvas {border-bottom: 1px solid #266fff;}</style></head><body><canvas></canvas><audio src="./123.mp3" controls></audio></body><script>const audioEle = document.querySelector('audio')const cvs = document.querySelector('canvas')const ctx = cvs.getContext('2d')// 初始化canvas尺寸function initCvs() {cvs.width = window.innerWidth * devicePixelRatiocvs.height = (window.innerHeight / 2) * devicePixelRatio}initCvs()// 初始化,只需要做一次就可以了let isInit = falselet dateArray = nulllet analyser = nullaudioEle.addEventListener('play', function (e) {if (isInit) return// 初始化const audCtx = new AudioContext() // 创建音频上下文const source = audCtx.createMediaElementSource(audioEle) // 创建音频源节点// 什么叫音频源节点?节点其实就是音频处理的一个环节。音频可能有很多环节 比如说修音 比如说混响 比如说把音调高调低这些都是处理环节// 每一个环节就是一个节点 在这些节点当中有一种叫源节点 表示我们音频数据的来源analyser = audCtx.createAnalyser()analyser.fftSize = 512 // 2的n次幂。数值越大越细腻// 创建数组 用于接收分析器节点的分析数据dateArray = new Uint8Array(analyser.frequencyBinCount) // 数组里面的每一项都是一个无符号的8位整数source.connect(analyser)analyser.connect(audCtx.destination)isInit = true})// 把分析出的波形绘制到canvas上function draw() {requestAnimationFrame(draw)// 清空画布const { width, height } = cvsctx.clearRect(0, 0, width, height)if (!isInit) return// 让分析器节点分析出数据到数组中analyser.getByteFrequencyData(dateArray)const len = dateArray.length / 2.5ctx.fillStyle = '#266fff'const barWidth = width / len / 2for (let i = 0; i < len; i++) {const data = dateArray[i] // < 256const barHeight = (data / 255) * heightconst x1 = i * barWidth + width / 2const x2 = width / 2 - (i + 1) * barWidthconst y = height - barHeightctx.fillRect(x1, y, barWidth - 2, barHeight)ctx.fillRect(x2, y, barWidth - 2, barHeight)}}draw()</script> </html>
相关文章:
前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。
1、演示 2、代码分析 逐行解析 JavaScript 代码块: const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用,并使用…...
【计算机毕业设计】基于Java+SSM的实战开发项目150套(附源码+演示视频+LW)
大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 🧡今天给大家分享150的Java毕业设计,基于ssm框架,这些项目都经过精心挑选,涵盖了不同的实战主题和用例,可做毕业设计和课程…...
STM32H7的MPU学习和应用示例
STM32H7的MPU学习记录 什么是MPU?MPU的三种内存类型内存映射MPU保护区域以及优先级 MPU的寄存器XN位AP位TEX、C、B、S位SRD 位SIZE 位CTRL 寄存器的各个位 示例总结 什么是MPU? MPU(Memory Protection Unit,内存保护单元…...
964: 数细胞
样例: 解法: 1.遍历矩阵 2.判断矩阵[i][j],若是未标记细胞则遍历相邻所有未标记细胞并标记,且计数 实现:遍历相邻所有未标记细胞 以DFS实现: function dfs(当前状态) {if (终止条件) {}vis[标记当前状…...
流程图步骤条
1.结构 <ul class"stepUl"> <li class"stepLi" v-for"(item, index) in stepList" :key"index"> <div class"top"> <p :class"{active: currentState > item.key}">{{ item.value }}…...
GPT知识库浅析
一、引言 上篇文章《GPT简介及应用》介绍了GPT的应用场景,里面提到GPT bot的基本使用:基于GPT训练好的数据,回答用户的问题。 但在使用过程中,如果用户的问题里面出现最新的术语,就会出现这种提示: 截至我…...
SpringMVC--SpringMVC的视图
目录 1. 总述 2. ThymeleafView视图 3. 转发视图 4. 重定向视图 5. 视图控制器view-controller 1. 总述 在SpringMVC框架中,视图(View)是一个非常重要的概念,它负责将模型数据(Model)展示给用户。简单…...
Datax,hbase与mysql数据相互同步
参考文章:datax mysql 和hbase的 相互导入 目录 0、软件版本说明 1、hbase数据同步至mysql 1.1、hbase数据 1.2、mysql数据 1.3、json脚本(hbase2mysql.json) 1.4、同步成功日志 2、mysql数据同步至hbase 1.1、hbase数据 1.2、mysql…...
ubuntu spdlog 封装成c++类使用
安装及编译方法:ubuntu spdlog 日志安装及使用_spdlog_logger_info-CSDN博客 h文件: #ifndef LOGGING_H #define LOGGING_H#include <iostream> #include <cstring> #include <sstream> #include <string> #include <memor…...
【C语言】——字符串函数的使用与模拟实现(上)
【C语言】——字符串函数 前言一、 s t r l e n strlen strlen 函数1.1、函数功能1.2、函数的使用1.3、函数的模拟实现(1)计数法(2)递归法(3)指针 - 指针 二、 s t r c p y strcpy strcpy 函数2.1、函数功能…...
数据库(1)
目录 1.什么是事务?事务的基本特性ACID? 2.数据库中并发一致性问题? 3.数据的隔离等级? 4.ACID靠什么保证的呢? 5.SQL优化的实践经验? 1.什么是事务?事务的基本特性ACID? 事务指…...
VirtualBox - 与 Win10 虚拟机 与 宿主机 共享文件
原文链接 https://www.cnblogs.com/xy14/p/10427353.html 1. 概述 需要在 宿主机 和 虚拟机 之间交换文件复制粘贴 貌似不太好使 2. 问题 设置了共享文件夹之后, 找不到目录 3. 环境 宿主机 OS Win10开启了 网络发现 略虚拟机 OS Win10开启了 网络发现 略Virtualbox 6 4…...
深入浅出 useEffect:React 函数组件中的副作用处理详解
useEffect 是 React 中的一个钩子函数,用于处理函数组件中的副作用操作,如发送网络请求、订阅消息、手动修改 DOM 等。下面是 useEffect 的用法总结: 基本用法 import React, { useState, useEffect } from react;function Example() {cons…...
《QT实用小工具·十九》回车跳转到不同的编辑框
1、概述 源码放在文章末尾 该项目实现通过回车键让光标从一个编辑框跳转到另一个编辑框,下面是demo演示: 项目部分代码如下: #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : p…...
基本的数据类型在16位、32位和64位机上所占的字节大小
1、目前常用的机器都是32位和64位的,但是有时候会考虑16位机。总结一下在三种位数下常用的数据类型所占的字节大小。 数据类型16位(byte)32位(byte)64位(byte)取值范围char111-128 ~ 127unsigned char1110 ~ 255short int / short222-32768~32767unsigned short222…...
关注招聘 关注招聘 关注招聘
🔥关注招聘 🔥关注招聘 🔥关注招聘 🔥开源产品: 1.农业物联网平台开源版 2.充电桩系统开源版 3.GPU池化软件(AI人工智能训练平台/推理平台) 开源版 产品销售: 1.农业物联网平台企业版 2.充电桩系统企业…...
Django框架设计原理
相信大多数的Web开发者对于MVC(Model、View、Controller)设计模式都不陌生,该设计模式已经成为Web框架中一种事实上的标准了,Django框架自然也是一个遵循MVC设计模式的框架。不过从严格意义上讲,Django框架采用了一种更…...
Linux ARM平台开发系列讲解(QEMU篇) 1.2 新添加一个Linux kernel设备树
1. 概述 上一章节我们利用QEMU成功启动了Linux kernel,但是细心的小伙伴就会发现,我们用默认的defconfig是没有找到设备树源文件的,但是又发现kernel启动时候它使用了设备树riscv-virtio,qemu,这是因为qemu用了一个默认的设备树文件,该章节呢我们就把这个默认的设备树文件…...
OSPF动态路由实验(思科)
华为设备参考: 一,技术简介 OSPF(Open Shortest Path First)是一种内部网关协议,主要用于在单一自治系统内决策路由。它是一种基于链路状态的路由协议,通过链路状态路由算法来实现动态路由选择。 OSPF的…...
MyBatis 等类似的 XML 映射文件中,当传入的参数为空字符串时,<if> 标签可能会导致 SQL 语句中的条件判断出现意外结果。
问题 传入的参数为空字符串,但还是根据参数查询了。 原因 在 XML 中使用 标签进行条件判断时,需要明确理解其行为。在 MyBatis 等类似的 XML 映射文件中, 标签通常用于动态拼接 SQL 语句的条件部分。当传入的参数 riskLevel 为空字符串时…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
