Search code examples
javascriptvisualizer

JS music visulalizer


I am trying to make a music visualizer in Javascript in the shape of circle, my problem is that even though I call clearRect, the canvas isnt clearing after a completion of a cycle.

$(document).ready(function() {
  var canvas = document.getElementsByTagName("canvas")[0];
  var context = canvas.getContext("2d");

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  context.translate(window.innerWidth / 2, window.innerHeight / 2);

  var audioContext = new AudioContext();
  var audio = document.getElementsByTagName('audio')[0];
  var source = audioContext.createMediaElementSource(audio);
  var analyser = audioContext.createAnalyser();

  source.connect(analyser);
  analyser.connect(audioContext.destination);

  var BLenght = analyser.frequencyBinCount;
  var data = new Uint8Array(BLenght);

  function Visualizer() {
    context.clearRect(0, 0, canvas.width, canvas.height);
    analyser.getByteFrequencyData(data);

    var fwidth = (canvas.width / BLenght);
    var fheight = 0;

    var maxCircle = 80;
    var radius = 200;

    for (var i = 0; i <= maxCircle; i++) {
      fheight = (data[i] * (canvas.height * 0.003)) / 2;

      context.fillStyle = "#000000";
      context.rect(0, radius, fwidth, fheight);
      context.rotate(2 * Math.PI / maxCircle);
      context.fill();
    }

    call = requestAnimationFrame(Visualizer);
  }

  var button = document.getElementById("button");
  var isPlaying = false;

  button.addEventListener('click', function() {
    if (isPlaying == false) {
      audio.play();
      Visualizer();
      isPlaying = true;
      button.style.boxShadow = "0px 0px 0px 0px #065e41";
      var delay = 400;
      setTimeout(function() {
        button.style.boxShadow = "0px 5px 0px 0px #065e41";
      }, delay);


    } else {
      audio.pause();
      isPlaying = false;
      cancelAnimationFrame(call);
      button.style.boxShadow = "0px 0px 0px 0px #065e41";
      var delay = 400;
      setTimeout(function() {
        button.style.boxShadow = "0px 5px 0px 0px #065e41";
      }, delay);
    }
  });



});
* {
  box-sizing: border-box;
}
canvas {
  position: absolute;
  top: 10%;
}
#button {
  width: 150px;
  height: 50px;
  background: #0deaa1;
  text-align: center;
  border-radius: 5px;
  box-shadow: 0px 5px 0px 0px #065e41;
  cursor: pointer;
  user-select: none;
  transition: .5s;
}
#button h1 {
  padding-top: 7px;
  color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1715/the_xx_-_intro.mp3" preload="auto"></audio>

<canvas></canvas>

<div id="button">
  <h1>PLAY</h1>
</div>
<p id="width">width</p>
<p id="buffer">buffer</p>
<p id="data">data</p>


Solution

  • It can be fixed by using fillRect, or by using context.beginPath. (currently you are adding every rect to the same path)

    context.fillStyle = "#000000"; 
    context.fillRect(0,radius,fwidth,fheight); // rect changed to fillrect
    context.rotate(2*Math.PI/maxCircle);
    

    To prevent the lines from spinning: reset the context transformation matrix:

    context.setTransform(1, 0, 0, 1, 0, 0);
    context.translate(window.innerWidth/2,window.innerHeight/2);
    context.clearRect(-canvas.width/2,-canvas.height/2,canvas.width,canvas.height);
    

    The Codepen example you provided was also updated: http://codepen.io/anon/pen/xbMxzY