目 录CONTENT

文章目录

AudioContext实现音乐盒

Administrator
2021-05-13 / 0 评论 / 7 点赞 / 5895 阅读 / 4455 字 / 正在检测是否收录...

AudioContext实现音乐盒

  • 时间:2021年5月13日
  • 人员:杨标
  • 名称:AudioContext实现音乐盒动态效果
  • 技术点:AudioContext API,Audio使用,canvas的使用

效果图

image.png

案例说明

通过AudioContext 的API来读取音乐音频数据,然后通过如上图所示的东西展示出来

本案列主要使用AudioContext的API,Canvas画布内容,Uint8Array等技术点

代码

index.html

<!DOCTYPE html>
<html lang="zh">

<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>audioContext Demo</title>
    <style>
        #c1 {
            background-color: #000;
            display: block;
            margin: auto;
        }
    </style>
</head>

<body>
    <canvas id="c1" width="1440" height="600"></canvas>
    <button type="button" id="btnStart">开始</button>
    <button type="button" id="btnStop">结束</button>
</body>
<script src="./js/index.js"></script>

</html>

index.js

class Rectangle {
    constructor(index) {
        this.index = index;
        let baseWidth = 1440 / 30;
        this.x = index * baseWidth;
        this.width = baseWidth - 5;
        this.redY = 600 - 12;

    }
    setPower(bili, powerArr) {
        this.power = powerArr[parseInt(1440 / 30 * this.index * bili)];
        this.height = 600 * this.power / 255;
        this.y = 600 - this.height;
    }
    /**
     * 
     * @param {CanvasRenderingContext2D} ctx 
     */
    draw(ctx) {
        let baseHeight = 12;
        let rectCount = this.height / baseHeight;
        if (this.redY > this.y) {
            this.redY = this.y - 12;
        }
        else {
            this.redY += 2;
            if (this.redY > 600 - 12) {
                this.redY = 600 - 12;
            }
        }
        ctx.save();
        ctx.fillStyle = "red";
        ctx.fillRect(this.x, this.redY, this.width, baseHeight - 3);
        ctx.restore();
        for (let i = 0; i < rectCount; i++) {
            ctx.fillRect(this.x, this.y + i * baseHeight, this.width, baseHeight - 3);
        }
    }
}

let btnStart = document.getElementById("btnStart");
let btnStop = document.getElementById("btnStop");
/**
 * @type {HTMLCanvasElement}
*/
let c1 = document.getElementById("c1");
let ctx = c1.getContext("2d");
let grd = ctx.createLinearGradient(0, 0, 0, 600);
grd.addColorStop(0, "red");
grd.addColorStop(0.5, "yellow");
grd.addColorStop(1, "#00E800");
ctx.fillStyle = grd;

let rt_array = new Array();
for (let i = 0; i < 30; i++) {
    let rect = new Rectangle(i);
    rt_array.push(rect);
}

let AC = new AudioContext();
let analyser = AC.createAnalyser();
let gainNode = AC.createGain();
gainNode.gain.value = 1;
let audio = document.createElement("audio");
audio.src = "./assets/music2.mp3";
audio.load();
let audioSource = AC.createMediaElementSource(audio);

btnStart.onclick = function () {  
    audioSource.connect(analyser);
    analyser.connect(gainNode);
    gainNode.connect(AC.destination);

    audio.play();
    setInterval(() => {
        ctx.clearRect(0, 0, 1440, 600);
        let musicBufferArray = new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteFrequencyData(musicBufferArray);
        let arr = Array.prototype.slice.call(musicBufferArray);
        let bili = arr.length / c1.width;
        for (let i = 0; i < rt_array.length; i++) {
            let rt = rt_array[i];
            rt.setPower(bili, arr);
            rt.draw(ctx);
        }
    }, 1000 / 60);
}

btnStop.onclick = function () {
    audio.pause();
    audioSource.disconnect(analyser);
    analyser.disconnect(gainNode);
    gainNode.disconnect(AC.dispatchEvent);
}

//记录时间值的变化
audio.ontimeupdate = function (event) {
    console.log(event.target.currentTime);
}
7

评论区