canvas实现音频可视化

音频可视化

/**
 * 音频可视化
 */
export class AudioToCanvas {
  public canvas: HTMLCanvasElement
  public audioUrl: string
  public audio: any
  constructor(audioUrl: string, width: number = 512, height: number = 512, bgColor: string = 'rgb(255, 255, 255)') {
    this.audioUrl = audioUrl
    this.canvas = document.getElementById('canvas')! as HTMLCanvasElement
    this.canvas.width = 300
    this.canvas.height = 300
    this.canvas.style.background = bgColor
    this.audio = this.initAudio()
  }

  preview(): this {
    const canvas = this.canvas!
    canvas.style.position = 'fixed'
    canvas.style.top = '5%'
    canvas.style.left = '5%'
    document.body.appendChild(this.canvas)
    return this
  }

  initAudio() {
    const audio = document.createElement('audio')
    audio.src = this.audioUrl
    audio.play()
    return audio
  }

  onLoadAudio() {
    // this.canvas.style.backgroundColor = bgColor
    // 创建音频上下文
    const context = new AudioContext()
    // 创建分析器
    /**
     * 分析器:进行频谱分析,可以把时域图使用快速傅里叶变换 转成 频率图(快速傅里叶转换)
     */
    const analyser = context.createAnalyser()
    /** 数值越大,分析得越细腻 必须是2的N次幂 */
    analyser.fftSize = 512

    // 创建音频源节点
    const source = context.createMediaElementSource(this.audio)
    source.connect(analyser)
    analyser.connect(context.destination)

    const bufferLength = analyser.frequencyBinCount
    /** 创建字节数组 */
    const dataArray = new Uint8Array(bufferLength)

    const ctx = this.canvas.getContext('2d')!

    const barWidth = (this.canvas.width / bufferLength) * 1.5
    let barHeight

    const self = this

    return function () {
      // 清空画布
      ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
      // 让分析器节点分析出来的数据存入字节数组中
      analyser.getByteFrequencyData(dataArray)

      const len = bufferLength / 2
      for (let i = 0; i < len; i++) {
        barHeight = dataArray[i] // < 256

        const r = barHeight + 25 * (i / len)
        const g = 250 * (i / len)
        const b = 50
        const x1 = i * barWidth + self.canvas.width / 2
        const x2 = self.canvas.width / 2 - (i + 1) * barWidth
        const y = self.canvas.height - barHeight

        ctx.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')'
        ctx.fillRect(x1, y, barWidth - 1, barHeight)
        ctx.fillRect(x2, y, barWidth - 1, barHeight)
      }
    }
  }
}

/** 使用*/
import AudioToCanvas from './xxx/AudioToCanvas'

const instance = new AudioToCanvas('sounds/music.mp3')
const draw = instance.onLoadAudio()

function animate() {
    requestAnimationFrame(animate);
    draw()
}
animate()

效果

你可能感兴趣的:(notes,音视频,javascript)