title: JS Canvas - Can't draw smooth lines
body: <p>I've been trying to draw smooth lines on my canvas but I've had no luck. I've tried setting the lineCap to round, using quadratic instead of lineTo, but nothing worked.</p>
  <p>While the mouse moves, it records the position of the mouse into an array and then runs through the array to draw the lines.</p>
  <pre><code>**JavaScript**
  // GLOBAL VARIABLES - CONTAINER/CANVAS
  var wContainer  = document.getElementById('Whiteboard_Container');
  var layerGrid   = document.getElementById('LayerGrid');
  var lgctx       = layerGrid.getContext('2d');
  var layer1      = document.getElementById('Layer1');
  var l1ctx       = layer1.getContext('2d');
  
  // GLOBAL VARIABLES - MOUSE/TOUCH
  var cursorPos   = { top: 0, left: 0, x: 0, y: 0 };
  var cursorType  = 'mouse';  // USED TO CONTROL MOUSE/TOUCH
  var dragging    = false;    // SETS/STOPS DRAGGING CANVAS
  var dragLock    = false;    // USED TO PREVENT ACCIDENTAL DRAGGING (esp. touch)
  
  // GLOBAL VARIABLES - DRAWING
  var layer   = 'LAYER1';
  var vectors = [];
  
  // MOUSE EVENT LISTENERS
  layer1.addEventListener('mousedown', mouseDown);
  layer1.addEventListener('mouseup', mouseUp);
  
  // TOUCH EVENT LISTENERS
  layer1.addEventListener('touchstart', touchDown);
  layer1.addEventListener('touchend', touchUp);
  
  // INITIALISER
  function init()
  {
      resize();
  
      // SET PEN STYLE
      lgctx.strokeStyle = 'rgba(230, 230, 230, 1)';
      lgctx.lineWidth   = 1;
      lgctx.lineCap     = 'round';
      lgctx.lineJoin    = 'round';
  
      // SET PEN STYLE
      l1ctx.strokeStyle = 'rgba(0, 0, 0, 1)';
      l1ctx.lineWidth   = 10;
      l1ctx.lineCap     = 'round';
      l1ctx.lineJoin    = 'round';
  }
  init();
  
  // AUTO SIZE THE CANVAS
  function resize()
  {
      // SET THE CANVAS SIZE
      layerGrid.width     = window.innerWidth * 4;
      layerGrid.height    = window.innerHeight * 4;
      layer1.height       = window.innerHeight * 4;
      layer1.width        = window.innerWidth * 4;
      layer1.height       = window.innerHeight * 4;
  }
  
  // MOUSE DOWN
  function mouseDown(e)
  {
      // Set cursor type
      cursorType = 'mouse';
  
      // EMPTY CURRENT VECTOR LIST
      vectors = [];
      vectors.length = 0;
  
      if(e.button == 0) // LEFT MOUSE CLICK
      {
          layer1.addEventListener('mousemove', setVectors);
      }
      else if(e.button == 2 &amp;&amp; dragLock == false) // RIGHT MOUSE CLICK
      {
          dragging = true;
          layer1.addEventListener('mousemove', canvasDrag);
  
          // SET START SCROLL POSITION
          cursorPos.top  = wContainer.scrollTop;
          cursorPos.left = wContainer.scrollLeft;
  
          // SET CURSOR POSITION
          cursorPos.x = e.clientX;
          cursorPos.y = e.clientY;
      }
  }
  
  // MOUSE UP
  function mouseUp(e)
  {
      // PREVENT DRAGGING &amp; REMOVE GRID
      dragging = false;
      layer1.removeEventListener('mousemove', canvasDrag);
      layer1.removeEventListener('mousemove', setVectors);
      removeGrid();
  }
  
  // TOUCH DOWN
  function touchDown(e)
  {
      e.preventDefault();
  
      // Set cursor type
      cursorType = 'touch';
  
      // EMPTY CURRENT VECTOR LIST
      vectors = [];
      vectors.length = 0;
  
      if(e.touches.length == 1)       // SINGLE TOUCH
      {
          layer1.addEventListener('touchmove', setVectors);
      }
      else if(e.touches.length &gt; 1 &amp;&amp; dragLock == false)  // MULTI-TOUCH
      {
          dragging = true;
          layer1.addEventListener('touchmove', canvasDrag);
  
          // SET START SCROLL POSITION
          cursorPos.top  = wContainer.scrollTop;
          cursorPos.left = wContainer.scrollLeft;
  
          // SET CURSOR POSITION
          cursorPos.x = e.touches[0].clientX;
          cursorPos.y = e.touches[0].clientY;
      }
  }
  
  // TOUCH UP
  function touchUp(e)
  {
      // PREVENT DRAGGING &amp; REMOVE GRID
      dragging = false;
      layer1.removeEventListener('mousemove', canvasDrag);
      layer1.removeEventListener('touchmove', setVectors);
      removeGrid();
  }
  
  // HANDLE MOVEMENT
  function canvasDrag(e)
  {
      if(dragging == true &amp;&amp; cursorType == 'mouse')   // MOUSE DRAG
      {
          // DRAW GRID AS GUIDANCE
          drawGrid();
  
          const dx = e.clientX - cursorPos.x;
          const dy = e.clientY - cursorPos.y;
  
          wContainer.scrollTop  = cursorPos.top - dy;
          wContainer.scrollLeft = cursorPos.left - dx;
      }
      else if(dragging == true &amp;&amp; cursorType == 'touch' &amp;&amp; e.touches.length &gt; 1) // TOUCH DRAG
      {
          // DRAW GRID AS GUIDANCE
          drawGrid();
  
          const dx = e.touches[0].clientX - cursorPos.x;
          const dy = e.touches[0].clientY - cursorPos.y;
  
          wContainer.scrollTop  = cursorPos.top - dy;
          wContainer.scrollLeft = cursorPos.left - dx;
      }
  }
  
  // SET VECTORS
  function setVectors(e)
  {
      if(cursorType == 'mouse') // MOUSE DRAW
      {
          // Set the drawing vectors
          vectors.push({x:e.clientX + wContainer.scrollLeft, y:e.clientY + wContainer.scrollTop});
      }
      else if(cursorType == 'touch' &amp;&amp; e.touches.length == 1) // ONLY ALLOW IF SINGLE TOUCH
      {
          // Set the drawing vectors
          vectors.push({x:e.touches[0].clientX + wContainer.scrollLeft, y:e.touches[0].clientY + wContainer.scrollTop});
      }
  
      // Draw the path, based on the vectors array
      drawVectors();
  }
  
  // DRAW VECTORS
  function drawVectors()
  {
      l1ctx.beginPath();
      //l1ctx.clearRect(0, 0, layer1.width, layer1.height);
      for(var i = 0; i &lt; vectors.length - 2; i++)
      {
          var xc = (vectors[i].x + vectors[i + 1].x) / 2;
          var yc = (vectors[i].y + vectors[i + 1].y) / 2;
          l1ctx.quadraticCurveTo(vectors[i].x, vectors[i].y, xc, yc);
          //l1ctx.lineTo(vectors[i].x, vectors[i].y);
      }
      l1ctx.stroke();
  }
  
  // DRAW GRID
  function drawGrid()
  {
      lgctx.beginPath();
      for(var i = 0; i &lt; layer1.width; i = i + 100)
      {
          lgctx.moveTo(i, 0); 
          lgctx.lineTo(i, layer1.height);
      }
      lgctx.moveTo(0, 0);
      for(var i = 0; i &lt; layer1.height; i = i + 100)
      {
          lgctx.moveTo(0, i); 
          lgctx.lineTo(layer1.width, i);
      }
      lgctx.stroke();
      lgctx.closePath();
  }
  
  // REMOVE GRID
  function removeGrid()
  {
      lgctx.clearRect(0, 0, layerGrid.width, layerGrid.height);
  }
  </code></pre>
  <p>The first line is how its drawn, the second is how I'm trying to get it to appear:
  <a href="https://i.stack.imgur.com/QM4SE.png" rel="nofollow noreferrer">Line comparison</a></p>