新增第209个小实例:音频可视化
This commit is contained in:
parent
c64138afaf
commit
04a2b32549
|
@ -216,6 +216,7 @@
|
|||
206. HTML5+CSS3小实例:人物介绍卡片2.0
|
||||
207. HTML5+CSS3小实例:弹出式悬停效果
|
||||
208. HTML5+CSS3+JS小实例:五彩纸屑礼花筒
|
||||
209. HTML5+CSS3+JS小实例:音频可视化
|
||||
|
||||
#### 赞赏作者
|
||||
![image](https://gitee.com/wyanhui02/html_css_demo/raw/master/images/%E8%B5%9E%E8%B5%8F%E4%BD%9C%E8%80%85/%E8%B5%9E%E8%B5%8F%E7%A0%81.jpg)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
*{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body{
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: #000;
|
||||
}
|
||||
canvas{
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
audio{
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
opacity: 0.15;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
audio:hover{
|
||||
opacity: 1;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>音频可视化</title>
|
||||
<link rel="stylesheet" href="209.css">
|
||||
</head>
|
||||
<body>
|
||||
<canvas></canvas>
|
||||
<audio src="/mp3/夜曲.mp3" controls></audio>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script src="209.js"></script>
|
|
@ -0,0 +1,73 @@
|
|||
// 要操作的元素
|
||||
const audio=document.querySelector('audio');
|
||||
const cvs=document.querySelector('canvas');
|
||||
const ctx=cvs.getContext('2d');
|
||||
|
||||
// 初始化画布
|
||||
function initCvs(){
|
||||
cvs.width=window.innerWidth * devicePixelRatio;
|
||||
cvs.height=(window.innerHeight / 2) * devicePixelRatio;
|
||||
}
|
||||
|
||||
initCvs();
|
||||
|
||||
|
||||
// 是否已初始化
|
||||
let isInit=false;
|
||||
// 数组,用于接收分析器节点的分析数据
|
||||
let dataArray;
|
||||
// 分析器节点
|
||||
let analyser;
|
||||
// 音频播放事件
|
||||
audio.onplay=function(){
|
||||
// 判断是否初始化
|
||||
if(isInit){
|
||||
return;
|
||||
}
|
||||
|
||||
// 开始初始化
|
||||
// 创建音频上下文
|
||||
const audioCtx=new AudioContext();
|
||||
// 创建音频源节点
|
||||
const source=audioCtx.createMediaElementSource(audio);
|
||||
// 创建分析器节点
|
||||
analyser=audioCtx.createAnalyser();
|
||||
analyser.fftSize=512;
|
||||
// 接收分析器节点的分析数据
|
||||
dataArray=new Uint8Array(analyser.frequencyBinCount);
|
||||
source.connect(analyser);
|
||||
analyser.connect(audioCtx.destination);
|
||||
|
||||
// 已初始化
|
||||
isInit=true;
|
||||
}
|
||||
|
||||
// 把分析出来的波形绘制到canvas上
|
||||
function draw(){
|
||||
// 逐帧绘制
|
||||
requestAnimationFrame(draw);
|
||||
|
||||
// 接下来清空画布
|
||||
const { width, height } = cvs;
|
||||
ctx.clearRect(0,0,width,height);
|
||||
if(!isInit){
|
||||
return;
|
||||
}
|
||||
// 让分析器节点分析出数据到数组中
|
||||
analyser.getByteFrequencyData(dataArray);
|
||||
const len=dataArray.length / 2; //条的数量,取一半,前半部分(低频范围就好,高频部分人耳几乎听不到,看不到波形)
|
||||
const barWidth=width / len / 2; //条的宽度
|
||||
ctx.fillStyle='#e0f9b5';
|
||||
// 循环绘制
|
||||
for(let i=0;i<len;i++){
|
||||
const data=dataArray[i];
|
||||
const barHeight=(data / 255) * height; //条的高度
|
||||
const x1=i * barWidth + width / 2; //右边区域中条的x坐标
|
||||
const x2=width / 2 - (i + 1) * barWidth; //左边区域中条的x坐标 镜像
|
||||
const y=height - barHeight; //条的y坐标
|
||||
ctx.fillRect(x1,y,barWidth - 2,barHeight); //填充右边区域
|
||||
ctx.fillRect(x2,y,barWidth - 2,barHeight); //填充左边区域
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
Loading…
Reference in New Issue