如何修复画布中的颜色条?

问题描述 投票:0回答:1

我有 JavaScript 代码,可以绘制垂直条并根据平均音乐频率更改其颜色。我尝试更改每个条形的颜色以匹配前一个条形的颜色,但我得到了不同的颜色。

const fileInput = document.getElementById('fileInput');
const canvas = document.getElementById('canvas');
const canvasCtx = canvas.getContext('2d');
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

// Function to resize canvas
function resizeCanvas() {
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
}

window.addEventListener('resize', resizeCanvas);
resizeCanvas(); // Initial call to set canvas size

let barColors = [];
const defaultBarColors = [];

fileInput.addEventListener('change', function() {
  const file = this.files[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = function(e) {
      audioCtx.decodeAudioData(e.target.result, function(buffer) {
        visualize(buffer);
      });
    };
    reader.readAsArrayBuffer(file);
  }
});

let rev;

function visualize(buffer) {
  const source = audioCtx.createBufferSource();
  source.buffer = buffer;

  const analyser = audioCtx.createAnalyser();
  source.connect(analyser);
  analyser.connect(audioCtx.destination);

  analyser.fftSize = 512;
  const bufferLength = analyser.frequencyBinCount;
  const dataArray = new Uint8Array(bufferLength);

  source.start();
  draw();

  function draw() {
    requestAnimationFrame(draw);

    analyser.getByteFrequencyData(dataArray);

    canvasCtx.clearRect(0, 0, canvas.width, canvas.height);

    const barWidth = Math.floor(canvas.width / 5); 
    const sensitivity = 1; 

    const frequencyBands = [
      { from: 0, to: Math.floor(bufferLength * 0.2) },    // Low frequencies
      { from: Math.floor(bufferLength * 0.2), to: Math.floor(bufferLength * 0.4) },  // Low-mid frequencies
      { from: Math.floor(bufferLength * 0.4), to: Math.floor(bufferLength * 0.6) },  // Mid frequencies
      { from: Math.floor(bufferLength * 0.6), to: Math.floor(bufferLength * 0.8) },  // Upper-mid frequencies
      { from: Math.floor(bufferLength * 0.8), to: bufferLength }    // High frequencies
    ];

    let x = 0;

    for (let i = 0; i < frequencyBands.length; i++) { // 0,1,2,3,4 
      const { from, to } = frequencyBands[i];
      const sum = dataArray.slice(from, to).reduce((acc, val) => acc + val, 0);
      const avg = sum / (to - from);

      let colorValue = rev[i];

      if (avg > 0) {
        if (i > 0) {
          colorValue = rev[i - 1];
    
        } else if (i == 0) {
            colorValue = "rgb(255, 255, 255)"; // Если первая колонка, то белый цвет
        }
      } else {

        colorValue = rev[i];
      }
      


      canvasCtx.fillStyle = colorValue;
      const barHeight = Math.max((avg / 255) * canvas.height * sensitivity, canvas.height);  
      canvasCtx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);

      x += barWidth; 
    }
  }
}

function initializeCanvas() {
  const barWidth = Math.floor(canvas.width / 5);
  let x = 0;

  for (let i = 4; i >= 0; i--) {
    const colorValue = Math.floor(((i / 5) * (240 - 51)) + 51);
    const color = `rgb(${colorValue}, ${colorValue}, ${colorValue})`;

    defaultBarColors[i] = color;
    canvasCtx.fillStyle = color;
    canvasCtx.fillRect(x, 0, barWidth, canvas.height);

    x += barWidth;
  }  
  
  rev = defaultBarColors.reverse();
}

initializeCanvas();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title></title>
  <style>
    body, html {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
    }
    #canvas {
      width: 100%;
      height: 100vh;
      display: block;
    }
  </style>
</head>
<body>
  <input type="file" id="fileInput" accept="audio/*">
<canvas id="canvas"></canvas>
</body>
</html>

这里为每个栏设置颜色的主要部分:

  let colorValue = rev[i];

  if (avg > 0) {
    if (i > 0) {
      colorValue = rev[i - 1];

    } else if (i == 0) {
        colorValue = "rgb(255, 255, 255)"; // Если первая колонка, то белый цвет
    }
  } else {

    colorValue = rev[i];
  }

如果列是 0(第一个),我将颜色更改为白色。如果 avg > 0 我尝试获取上一个栏的颜色。否则我从 rev 数组设置默认颜色。

一些变化:

function draw() {
  requestAnimationFrame(draw);

  const numBars = 5;
  let bar = 0;
  analyser.getByteFrequencyData(dataArray);
  canvasCtx.fillStyle = "#000";
  canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
  const barWidth = canvas.width / numBars;

  for (let i = 0; i < numBars; i++) {
    const start = Math.floor(i * bufferLength / numBars);
    const end = Math.floor((i + 1) * bufferLength / numBars);

    let sum = 0;
    for (let j = start; j < end; j++) {
      sum += dataArray[j];
    }

    const avg = sum / (end - start);

 
    if (avg > 0) {
      currentColors[i] = avg; 
    } else {
      currentColors[i] = rev[i]; // Возвращаемся к исходному цвету
    }

    const rgbColor = `rgb(${currentColors[i]}, ${currentColors[i]}, ${currentColors[i]})`;

    canvasCtx.fillStyle = rgbColor;
    canvasCtx.fillRect(bar, 0, barWidth, canvas.height);

    bar += barWidth;
  }
}
javascript algorithm canvas
1个回答
0
投票

我认为就是您正在寻找的东西,但我可能是错的。

说明:

  • 我创建了一个名为
    currentColors
    的新数组,它将保存每个条形的当前颜色。
  • 使用与
    currentColors
    相同的初始颜色初始化
    defaultBarColors
    数组。
  • 更新
    colorValue
    的旧逻辑没有正确更新条形的颜色。因此,我们利用
    currentColors
    数组来跟踪这些更改并更新其值。
© www.soinside.com 2019 - 2025. All rights reserved.