title: HTML5 Canvas: Applying a gradient to shadow
body: <p>I was surprised to find out that apparently the canvas API does not allow you to apply gradients to shadows like this:</p>
  
  <pre><code>var grad = ctx.createLinearGradient(fromX, fromY, toX, toY);
  
  grad.addColorStop(0, "red");
  grad.addColorStop(1, "blue");
  
  ctx.strokeStyle = grad;
  ctx.lineWidth = 3;
  ctx.shadowBlur = 10;
  ctx.shadowColor = grad; // doesn't seem to work
  
  ctx.beginPath();
  ctx.moveTo(fromX, fromY);
  ctx.lineTo(toX, toY);
  ctx.closePath();
  ctx.stroke();
  </code></pre>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// linear gradient from start to end of line
  var canvas = document.getElementById('mycanvas'),
    ctx = canvas.getContext('2d'),
    fromX = 3,
    fromY = 3,
    toX = 197,
    toY = 197,
    grad = ctx.createLinearGradient(fromX, fromY, toX, toY);
  
  canvas.width = 200;
  canvas.height = 200;
  
  grad.addColorStop(0, "red");
  grad.addColorStop(1, "blue");
  
  ctx.strokeStyle = grad;
  ctx.lineWidth = 3;
  ctx.shadowBlur = 20;
  ctx.shadowColor = grad;
  
  ctx.beginPath();
  ctx.moveTo(fromX, fromY);
  ctx.lineTo(toX, toY);
  ctx.closePath();
  ctx.stroke();</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    background: black
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;canvas id="mycanvas"&gt;&lt;/canvas&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>One workaround is to simply draw the line/shape/etc. multiple times at different sizes and opacity to get a similar result:</p>
  
  <pre><code>var grad = ctx.createLinearGradient(fromX, fromY, toX, toY);
  
  canvas.width = 200;
  canvas.height = 200;
  
  grad.addColorStop(0, "red");
  grad.addColorStop(1, "blue");
  
  ctx.strokeStyle = grad;
  ctx.lineWidth = 3;
  //ctx.shadowBlur = 20;
  //ctx.shadowColor = grad;
  
  for (var i = 10; i &gt; 1; i--) {
    ctx.lineWidth = i;
    ctx.globalAlpha = 1 / i;
    ctx.beginPath();
    ctx.moveTo(fromX, fromY);
    ctx.lineTo(toX, toY);
    ctx.closePath();
    ctx.stroke();
  }
  </code></pre>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// linear gradient from start to end of line
  var canvas = document.getElementById('mycanvas'),
    ctx = canvas.getContext('2d'),
    fromX = 3,
    fromY = 3,
    toX = 197,
    toY = 197,
    grad = ctx.createLinearGradient(fromX, fromY, toX, toY);
  
  canvas.width = 200;
  canvas.height = 200;
  
  grad.addColorStop(0, "red");
  grad.addColorStop(1, "blue");
  
  ctx.strokeStyle = grad;
  ctx.lineWidth = 3;
  //ctx.shadowBlur = 20;
  //ctx.shadowColor = grad;
  
  for (var i = 10; i &gt; 1; i--) {
    ctx.lineWidth = i;
    ctx.globalAlpha = 1 / i;
    ctx.beginPath();
    ctx.moveTo(fromX, fromY);
    ctx.lineTo(toX, toY);
    ctx.closePath();
    ctx.stroke();
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>body {
    background: black;
    }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;canvas id="mycanvas"&gt;&lt;/canvas&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Here's the comparison. Although the change is subtle, the right image shows roughly the desired effect.</p>
  
  <p><a href="https://i.stack.imgur.com/LftfR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LftfR.png" alt="line1"></a>
  <a href="https://i.stack.imgur.com/SnV4z.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/SnV4z.png" alt="line2"></a></p>
  
  <p>Is there a better way of doing this? I imagine there's a more efficient way than drawing the same thing multiple times. Does anyone know of a library that provides this kind of functionality?</p>