title: ctx.fillRect From Vertical Center
body: <p>I wanted to make a canvas element to visualise the audio from a HTML5 audioplayer.</p>
  <p>To do this I used the following JS:</p>
  <pre><code>let start = function () {
    let audio = document.getElementById('audioplayer');
    let ctx = new AudioContext();
    let analyser = ctx.createAnalyser();
    let audioSrc = ctx.createMediaElementSource(audio);
    // we have to connect the MediaElementSource with the analyser
    audioSrc.connect(analyser);
    analyser.connect(ctx.destination);
    // we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
    // analyser.fftSize = 64;
    // frequencyBinCount tells you how many values you'll receive from the analyser
    let frequencyData = new Uint8Array(analyser.frequencyBinCount);
  
    // we're ready to receive some data!
    let canvas = document.getElementById('canvas'),
      cwidth = canvas.width,
      cheight = canvas.height - 2,
      meterWidth = 5, //width of the meters in the spectrum
      gap = 2, //gap between meters
      capHeight = 1,
      capStyle = '#fff',
      meterNum = 1200 / (10 + 2), //count of the meters
      capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame
    ctx = canvas.getContext('2d');
    let gradient = ctx.createLinearGradient(0, 0, 0, 300);
    gradient.addColorStop(1, '#92e657');
    gradient.addColorStop(0.5, '#92e657');
    gradient.addColorStop(0, '#92e657');
  
    // loop
    function renderFrame() {
      let array = new Uint8Array(analyser.frequencyBinCount);
      analyser.getByteFrequencyData(array);
      let step = Math.round(array.length / meterNum); //sample limited data from the total array
      ctx.clearRect(0, 0, cwidth, cheight);
      for (let i = 0; i &lt; meterNum; i++) {
        let value = array[i * step];
        if (capYPositionArray.length &lt; Math.round(meterNum)) {
          capYPositionArray.push(value);
        }
        ctx.fillStyle = capStyle;
        //draw the cap, with transition effect
        if (value &lt; capYPositionArray[i]) {
          ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
        } else {
          ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
          capYPositionArray[i] = value;
        }
        ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look
        ctx.fillRect(i * 12 /*meterWidth+gap*/, cheight - value + capHeight, meterWidth, cheight); //the meter
      }
      requestAnimationFrame(renderFrame);
    }
  
    renderFrame();
    // audio.play();
  };
  </code></pre>
  <p>While this does work, the only issue is that the rectangle fills from bottom to top. Is there a way I can get the rectangle to fill from the vertical center instead?</p>
  <p>EDIT: I realised I haven't explained the issue clearly enough so am making an update here and I'm adding the following picture below.</p>
  <p><a href="https://i.stack.imgur.com/m6DPM.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/m6DPM.jpg" alt="enter image description here" /></a></p>
  <p>So I want to draw my rectangle from the red part (which is what I was referring as the vertical center) so that when it grows, it increased by an equal amount up and down on the y axis. Is this possible or would I have to have two fillRect commands to do the up and down movement separately?</p>