前端:音频可视化(H5+js版本)

一、效果展示

HTML5+JS实现一个简单的音频可视化

二、代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>音频可视化</title>
    <style></style>
  </head>
  <body>
    <div
      style="
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
      "
    >
      <div
        class="musicBox"
        style="position: relative; width: 500px; height: 500px"
      >
        <canvas
          id="audioCanvas"
          width="500"
          height="500"
          style="position: absolute; left: 0; top: 0"
        ></canvas
        ><svg
          t="1716202136861"
          class="icon"
          viewBox="0 0 1024 1024"
          version="1.1"
          xmlns="http://www.w3.org/2000/svg"
          p-id="4458"
          width="68"
          height="68"
          style="
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
          "
        >
          <path
            d="M701.6 196.53m-15 0a15 15 0 1 0 30 0 15 15 0 1 0-30 0Z"
            fill="#E159D3"
            p-id="4459"
          ></path>
          <path
            d="M956.29 310.21a482.39 482.39 0 1 0-847.9 452v120.36c0 71.4 58.42 130.76 129.82 130.1a127.79 127.79 0 0 0 100.44-49.85 120.4 120.4 0 0 0 21-103.43c-5.58-21.49-11.71-59-11.71-71.71S354 737.47 359.62 716a120.4 120.4 0 0 0-21-103.43 128.55 128.55 0 0 0-209.75 9.13c-20.91-64.82-25.25-135-11.25-205.6 28.7-144.71 172.14-286.19 317.16-313.27C690.37 55.1 914.24 250.88 914.24 498a402.4 402.4 0 0 1-19.36 123.71 128.55 128.55 0 0 0-209.74-9.13 120.4 120.4 0 0 0-21 103.43c5.58 21.49 11.71 59 11.71 71.71s-6.13 50.22-11.71 71.71a120.4 120.4 0 0 0 21 103.43 127.8 127.8 0 0 0 101.67 49.85 128.59 128.59 0 0 0 128.58-128.62V762.25a483 483 0 0 0 40.9-452z m-767.9 381.87c0-26.24 20.49-48.33 46.71-49.34a48.41 48.41 0 0 1 40.41 18.85 39.94 39.94 0 0 1 6.78 34.34c-5.84 22.48-14.29 68.12-14.29 91.85s8.45 69.37 14.29 91.85a39.94 39.94 0 0 1-6.78 34.37A48.38 48.38 0 0 1 237 932.86a48.64 48.64 0 0 1-48.64-48.64z m647 191.4c0 26.24-20.49 48.33-46.71 49.34a48.41 48.41 0 0 1-40.4-18.82 39.94 39.94 0 0 1-6.78-34.34c5.84-22.48 14.29-68.12 14.29-91.85s-8.45-69.37-14.29-91.85a39.94 39.94 0 0 1 6.78-34.34 48.41 48.41 0 0 1 40.41-18.85c26.22 1 46.71 23.1 46.71 49.34z"
            fill="#E159D3"
            p-id="4460"
          ></path>
          <path
            d="M651.51 154.09a371.39 371.39 0 0 0-419.35 100.28 373.69 373.69 0 0 0-30.07 39.56 15 15 0 1 0 25 16.52A341.48 341.48 0 0 1 512 157a339.17 339.17 0 0 1 128.23 24.93 15 15 0 1 0 11.29-27.79z"
            fill="#E159D3"
            p-id="4461"
          ></path>
          <path
            d="M456.91 668.17c-20.66 1.25-37.52 19.95-37.52 40.65v157.92c0 20.7 16.85 39.4 37.52 40.65a40 40 0 0 0 42.48-39.93V708.1a40 40 0 0 0-42.48-39.93zM563.91 698.12c-20.66 1.25-37.52 19.95-37.52 40.65v98c0 20.7 16.85 39.4 37.52 40.65a40 40 0 0 0 42.48-39.93V738a40 40 0 0 0-42.48-39.88z"
            fill="#48BCFF"
            p-id="4462"
          ></path>
        </svg>
      </div>

      <audio id="audio" src="./audio/游戏城大冒险.mp3" controls></audio>
    </div>
  </body>
  <script>
    //需要可视化的数据
    let audioArr;
    //我们需要一个音乐播放器和一个canvas进行显示
    const audioElement = document.getElementById("audio");
    const canvas = document.getElementById("audioCanvas");

    //canvas的一些基本设置
    const ctx = canvas.getContext("2d");
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const radius = 50; // 圆的半径

    //初始化
    let isInit = false;

    let analyser = null;

    // 当音乐播放
    audioElement.onplay = () => {
      if (!isInit) {
        isInit = true;
      }

      const audioContext = new AudioContext(); // 创建音频上下文
      const audioSrc = audioContext.createMediaElementSource(audioElement); // 创建音频源
      analyser = audioContext.createAnalyser(); // 创建分析器
      analyser.fftSize = 128; // 设置傅里叶变换的大小,影响线条密度
      audioArr = new Uint8Array(analyser.frequencyBinCount); // 创建一个无符号字节数组存储频率数据,该API参考ES6文档
      audioSrc.connect(analyser); // 连接音频源和分析器
      analyser.connect(audioContext.destination); // 连接分析器和音频目的地

      //动画开始
      animate();
    };

    // 绘制圆形
    const drawGradientCircle = () => {
      ctx.beginPath();
      // 创建一个从中心点向外的径向渐变
      const grd = ctx.createLinearGradient(
        centerX - radius,
        centerY - radius,
        centerX + radius,
        centerY + radius
      );
      grd.addColorStop("0", "purple");
      grd.addColorStop("0.3", "magenta");
      grd.addColorStop("0.5", "blue");
      grd.addColorStop("0.6", "green");
      grd.addColorStop("0.8", "yellow");
      grd.addColorStop(1, "red");

      ctx.strokeStyle = grd;

      ctx.arc(centerX, centerY, radius - 2, 0, Math.PI * 2); // 绘制一个完整的圆

      ctx.stroke(); // 画圆复制代码
    };

    //绘制线条
    const drawLinesFromCircle = () => {
      ctx.lineWidth = 2;

      //使用音频的频率数据绘制线条
      //为了美观,我们绘制两条线,一条是频率数据,另一条是对称的
      //也可以去使用其它的方式绘制线条
      audioArr.forEach((value, index) => {
        const baseAngle = (index / audioArr.length) * Math.PI * 2; // 基础角度
        const angle1 = baseAngle; // 第一条线的角度
        const angle2 = baseAngle + Math.PI; // 对称线的角度,相差π(180度)

        // 绘制第一条线
        {
          const endX1 = centerX + radius * Math.cos(angle1);
          const endY1 = centerY + radius * Math.sin(angle1);
          const startX1 = centerX + (radius + value * 0.4) * Math.cos(angle1); // 使用value控制长度
          const startY1 = centerY + (radius + value * 0.4) * Math.sin(angle1);

          ctx.beginPath();
          ctx.moveTo(startX1, startY1);
          ctx.lineTo(endX1, endY1);
          ctx.strokeStyle = `hsl(${index * 3.6}, 100%, 50%)`;
          ctx.stroke();
        }

        // 绘制对称的第二条线
        {
          const endX2 = centerX + radius * Math.cos(angle2);
          const endY2 = centerY + radius * Math.sin(angle2);
          const startX2 = centerX + (radius + value * 0.4) * Math.cos(angle2);
          const startY2 = centerY + (radius + value * 0.4) * Math.sin(angle2);

          ctx.beginPath();
          ctx.moveTo(startX2, startY2);
          ctx.lineTo(endX2, endY2);
          ctx.strokeStyle = `hsl(${
            (index + audioArr.length / 2) * 3.6
          }, 100%, 50%)`; // 调整颜色以保持对称性且有所区别
          ctx.stroke();
        }
      });
    };

    //播放动画
    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
      if (!isInit) return;
      analyser.getByteFrequencyData(audioArr); // 获取频率数据
      drawGradientCircle(); // 绘制圆形
      drawLinesFromCircle(); // 绘制伸展的线条
      requestAnimationFrame(animate); // 重复绘制以创建动画效果
    };
  </script>
</html>

三、VUE3+TS版本

前端:音频可视化(VUE3+TS版本)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633666.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-19讲 串口实验UART

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

【python】python社交交友平台系统设计与实现(源码+数据库)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Nginx企业级负载均衡:技术详解系列(9)—— Nginx核心配置详解(全局配置)

你好&#xff0c;我是赵兴晨&#xff0c;97年文科程序员。‍‍‍‍‍ 在 Nginx企业级负载均衡&#xff1a;技术详解系列&#xff08;8&#xff09;—— Nginx核心配置详解&#xff08;默认配置文件&#xff09;文章中&#xff0c;咱们讨论了Nginx核心配置文件的基础知识&#…

鸿蒙 DevEcoStudio:通知栏通知实现

【使用notificationManager实现通知栏功能】 【普通通知、长文本通知、多行通知、图片通知】 import notificationManager from ohos.notificationManager import image from ohos.multimedia.image Entry Component struct Index {State message: string Hello World// 将图…

Spring 事务源码分析

前言&#xff1a; 我们知道 Spring 声明式事务是通过 AOP 来实现的&#xff0c;日常项目开发中我们只需要使用 Transactional 注解就可以实现声明式事务&#xff0c;那你知道通过 Transactional 注解怎样实现事务的吗&#xff1f;本篇我们将从源码来分析 Spring 声明式事务的执…

鸿蒙HarmonyOS开发中的易混点归纳-持续补充中

相关文章目录 鸿蒙HarmonyOS开发术语全解&#xff1a;小白也能看懂&#xff01; 文章目录 相关文章目录前言一、build()函数和Builder装饰器&#xff1f;二、自定义组件和系统组件&#xff08;内置组件&#xff09;三、组件和页面四、自定义弹窗和其他弹窗总结 前言 一、build…

骨传导耳机哪个牌子好?五大热门精选推荐,真心力荐!

作为一名运动达人&#xff0c;在日常运动中经常会使用一些运动耳机&#xff0c;由于运动场景的特殊性&#xff0c;所以骨传导耳机凭借特殊的佩戴方式和独特的传声原理&#xff0c;所以骨传导耳机就成运动中的得力助手。然而&#xff0c;近期许多消费者在购买时往往被网络上的流…

冯喜运:5.24现货黄金趋势解读,黄金原油行情分析及操作建议

【黄金消息面分析】&#xff1a;美国劳工部公布的最新数据显示&#xff0c;截至5月18日的一周内&#xff0c;首次申请失业救济人数下降至21.5万人&#xff0c;创下自去年9月以来的最大降幅。数据公布后&#xff0c;现货黄金短线下挫6美元&#xff0c;报2362.71美元/盎司。这表明…

STM32入门笔记(02):USART串口通信注意事项笔记(SPL库函数版)

这是通过串口通信发送过来的数据&#xff0c;里面包括了故障码&#xff0c;电压&#xff0c;电流&#xff0c;频率等信息&#xff0c;请你用STM32f103系列单片机的串口1读取该数据并解析出电压和电流是多少&#xff1f; 要用STM32F103系列单片机的串口1读取并解析发电机上的逆…

一顿五元钱的午餐

在郑州喧嚣的城市一隅&#xff0c;藏着一段鲜为人知的真实的故事。 故事的主角是一位年过半百的父亲&#xff0c;一位平凡而又伟大的劳动者。岁月在他脸上刻下了深深的痕迹&#xff0c;但他眼神中闪烁着不屈与坚韧。 他今年52岁&#xff0c;为了给远在家乡的孩子们一个更好的…

MySQL 将json转为行,JSON_TABLE函数详解

MySQL 将json转为行&#xff0c;JSON_TABLE函数详解 JSON_TABLE 是 MySQL 8.0 引入的一个强大函数&#xff0c;它用于将 JSON 数据转换为关系表的格式。通过 JSON_TABLE 函数&#xff0c;可以将 JSON 文档解析为关系表的列和行&#xff0c;使得在 SQL 查询中处理 JSON 数据更加…

RocketMQ之DefaultPushConsumer

DefaultMQPushConsumer消息链路 DefaultMQpushConsumer#start方法调用DefaultMQpushConsumerImpl#start方法,接着内部调用MQClientInstance#start方法,接着调用RebalanceService#start方法。 RebalanceService#start方法开启一个线程,执行本类中的runnable#run方法。run方法…

P6【知识点】【数据结构】【树tree】C++版

树是由一个集合以及在该集合上定义的一种关系构成的&#xff0c;集合中的元素称为树的结点&#xff0c;所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构&#xff0c;在这种层次结构中有一个结点具有特殊的地位&#xff0c;这个结点称为该树的根结点。 二叉…

数据库|基于T-SQL创建数据库

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; SQL Server用于操作数据库的编程语言为Transaction-SQL,简称T-SQL。 本节学习基于T-SQL创建数据库。以下为学习笔记。 01 打开新建查询 首先连接上数据库&#xff0c;点击【新建查询】打开新建查询窗口&#xff0c; …

如何在go项目中实现发送邮箱验证码、邮箱+验证码登录

前期准备 GoLand &#xff1a;2024.1.1 下载官网&#xff1a;https://www.jetbrains.com/zh-cn/go/download/other.html Postman&#xff1a; 下载官网&#xff1a;https://www.postman.com/downloads/ 效果图(使用Postman) Google&#xff1a; QQ&#xff1a; And …

java 8--Lambda表达式,Stream流

目录 Lambda表达式 Lambda表达式的由来 Lambda表达式简介 Lambda表达式的结构 Stream流 什么是Stream流&#xff1f; 什么是流呢&#xff1f; Stream流操作 中间操作 终端操作 Lambda表达式 Lambda表达式的由来 Java是面向对象语言&#xff0c;除了部分简单数据类型…

SpringBoot——整合MyBatis

目录 MyBatis 项目总结 1、创建SQL表 2、新建一个SpringBoot项目 3、pom.xml添加依赖 4、application.properties配置文件 5、User实体类 6、UserMapper接口 7、UserMapper.xml映射文件 8、UserController控制器 9、SpringBootMyBatisApplication启动类 10、使用Po…

关于如何创建一个可配置的 SpringBoot Web 项目的全局异常处理

前情概要 这个问题其实困扰了我一周时间&#xff0c;一周都在 Google 上旅游&#xff0c;我要如何动态的设置 RestControllerAdvice 里面的 basePackages 以及 baseClasses 的值呢&#xff1f;经过一周的时间寻求无果之后打算决定放弃的我终于找到了一些关键的线索。 当然在此…

反射的基本知识

基本概念 反射是java在运行过程中的自我观察能力&#xff0c;通过class constructor field method 四个方法来获取一个类的各个组成部分。 反射是在运行状态中对于任意一个类&#xff0c;都能知道这个类的所有属性和方法&#xff1b;对于任意一个对象都能调用它的任意一个方法…

《MySQL是怎样运行的》快速查询秘籍——B+树索引

一.引出索引 前面一章我们说出了数据页的结构&#xff0c;但是如果我们要查找某一条记录的话&#xff0c;怎么办呢&#xff1f; 我们前面知道页与页之间是一个双向链表实现的&#xff0c;我们要找的话&#xff0c;是不是要按照这个链表一个一个找下去&#xff0c;然后找到&am…