# 音频可视化

后面补全

class AudioVisible {
  constructor(containerId = "") {
    this.$container = document.getElementById(containerId);
    this.$input = null;
    this.$canvas = null;
    this.canvasCtx = null;

    this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    this.source = this.audioCtx.createBufferSource();
    this.analyser = this.audioCtx.createAnalyser();
    this.bufferLength = 0;
    this.dataArray = []; //一个数组,元素为音频中每个频率的大小值(Number),长度为128
    this.maxAudioValue = 256;

    this.initElements();
  }

  initElements() {
    this.$input = document.createElement("input");
    this.$input.type = "file";
    this.$canvas = document.createElement("canvas");
    this.canvasCtx = this.$canvas.getContext("2d");

    // settings
    this.$canvas.width = 800;
    this.$canvas.height = 400;

    this.$container.append(this.$input);
    this.$container.append(this.$canvas);
    this.bindInputEvent();
  }

  bindInputEvent() {
    const reader = new FileReader();

    this.$input.onchange = (event) => {
      const file = event.target.files[0];
      reader.readAsArrayBuffer(file);
    };

    reader.onload = (event) => {
      const arrayBuffer = event.target.result;
      this.onDecode(arrayBuffer);
    };
  }

  onDecode(arrayBuffer) {
    this.audioCtx.decodeAudioData(
      arrayBuffer,
      (buffer) => {
        this.source.buffer = buffer;
        this.source.loop = true;
        this.source.connect(this.audioCtx.destination);
        this.source.start(0);
        this.source.connect(this.analyser);
        this.analyser.connect(this.audioCtx.destination);
        this.analyser.fftSize = this.maxAudioValue;
        this.bufferLength = this.analyser.frequencyBinCount;
        this.dataArray = new Uint8Array(this.bufferLength);

        this.onDrawCanvas();
      },
      (err) => console.error(err)
    );
  }

  onDrawCanvas() {
    const { width, height } = this.$canvas;
    const lineOffsetBase = width / this.bufferLength;
    this.canvasCtx.fillRect(0, 0, width, height);
    this.analyser.getByteFrequencyData(this.dataArray);

    this.canvasCtx.strokeStyle = "#ffffff";
    this.canvasCtx.beginPath();
    for (let i = 0; i < this.bufferLength; i++) {
      const x = i * lineOffsetBase;
      const y = height - (this.dataArray[i] / this.maxAudioValue) * height;
      this.canvasCtx.moveTo(x, height);
      this.canvasCtx.lineTo(x, y);
      this.canvasCtx.stroke();
    }

    requestAnimationFrame(this.onDrawCanvas.bind(this));
  }
}
Last Updated: 12/10/2020, 6:21:38 PM