javascripthtml5-canvaslinear-gradients

I can't get consecutive canvas rectangles to have the duplicate linear-gradient in js. Anyone know how?


I drew a canvas with consecutive rectangles each with it's own linear-gradient, but I am unable to make the linear-gradient show up on the rectangles except in the first rectangle. Each rectangle is the same size and every rectangle should have the same linear gradient. I was able to make only the first rectangle have the correct gradient, but none of the rest have it. The rest are black. Been looking all over the internet and can't find the answer. Where did I go wrong? Thanks!

Here is a pen with my code: https://codepen.io/monamoves/pen/RQvzOe

And here it is again.

HTML:

<canvas id="fabric" width="1020" height="300">
</canvas>

CSS:

canvas {
  border: thin red solid;
}

JavaScript:

window.onload = draw;

function draw() {
var cvs = document.getElementById("fabric");
var ctx = cvs.getContext("2d");

var xcoordinate = 0;
var grd = ctx.createLinearGradient(xcoordinate, 0, xcoordinate + 20, 0);

for (var i = 0; i < 50; i++) {
  ctx.beginPath();
  ctx.strokeStyle="#ccc";
  ctx.moveTo(xcoordinate, 0);
  ctx.rect(xcoordinate, 0, 20, 300);
  ctx.stroke();
  ctx.fillStyle = grd;
  grd.addColorStop(0, "black");
  grd.addColorStop(0.5, "white");
  grd.addColorStop(1, "black");
  ctx.fill();
  xcoordinate = xcoordinate + 20;  
}
}

Solution

  • You are defining your gradient once to be over your first rectangle only. Gradients don't follow your shape, if you tell it to be 20px wide at coords 0,0 every shape drawn outside these coordsa will be one of the 2 extreme colors you did set.

    You could create a new gradient at every iteration inside your for loop, and actually you would have to do so if you wanted to change its colorStops.

    But the best solution in your case (single gradient) is to declare only once your gradient, set only once its colorStops, and simply modify the transformation matrix of your context; gradients are also affected.

    var ctx = cvs.getContext("2d");
    
    var xcoordinate = 0;
    // set all this only once if it doesn't change
    var grd = ctx.createLinearGradient(0, 0, 20, 0);
    ctx.fillStyle = grd;
    grd.addColorStop(0, "black");
    grd.addColorStop(0.5, "white");
    grd.addColorStop(1, "black");
    ctx.strokeStyle="#ccc";
    
    for (var i = 0; i < 50; i++) {
      ctx.beginPath();
      // we move the transform matrix
      ctx.setTransform(1,0,0,1,xcoordinate,0);
      // and draw always at same coords
      ctx.moveTo(0, 0);
      ctx.rect(0, 0, 20, 300);
      ctx.stroke();
      ctx.fill();
      xcoordinate = xcoordinate + 20;  
    }
    <canvas id=cvs></canvas>