How to display a smoother gradient in HTML5 canvas

2019-07-20 12:31发布

I have a html5 canvas in my web page. I have only put an image and a gradient in it.

Canvas uses thic JS code to draw itself:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.clearRect ( 0 , 0 , canvas.width, canvas.height );
var img = document.getElementById("slika");
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
var grd = ctx.createLinearGradient(x-400, 0, x, 0)
grd.addColorStop(0.3,"hsla(360, 100%, 100%, 0)");
grd.addColorStop(1,"hsla(360, 100%, 100%, 0.8)");
ctx.fillStyle=grd;
ctx.fillRect(0,0,canvas.width,canvas.height);

ctx.font = "70px Arial";
ctx.fillStyle = "black"
ctx.textAlign = "right";
ctx.fillText(textInput,canvas.width-50,canvas.height-120);

When it displays, the transition isn't very smooth, it just starts somewhere and ends somewhere.

It looks like this:

http://kendaj.net46.net/canvas-StackOverflow.png

I would like the transition to be smoother(I don't mean a wider gradient).

Is there any way to do that?

Thanks for answering.

2条回答
成全新的幸福
2楼-- · 2019-07-20 12:53

If by "smoother" you mean transition more gradually, then you need to adjust your color stops. You don't need to adjust the width of the gradient to do that.

grd.addColorStop(0.3,"hsla(360, 100%, 100%, 0)");
grd.addColorStop(1,"hsla(360, 100%, 100%, 0.8)");

Right now, those stops are driven by this, so you're moving from the left at 0 alpha to 30%, which is where you jump to .8 in your alpha channel, if you want this to feel more gradual, then (depending on the effect you want) you should adjust those stops.

grd.addColorStop(0.0,"hsla(360, 100%, 100%, 0)");
grd.addColorStop(1,"hsla(360, 100%, 100%, 0.8)");

That would be more fluid, and you could reduce the alpha as desired. Again, it really depends on the effect you're seeking on the gradient overlay.

查看更多
Anthone
3楼-- · 2019-07-20 12:57

Use a s-slope based gradient which could be defined using an ease-in-out function. This way the transition between flat and linear is smoothed out. You may need to compensate a little on the width as initial and final values are closer to the flat values than in the linear approach.

easing

Example

result

var ctx = document.querySelector("canvas").getContext("2d"), img = new Image();
img.onload = function() {

  // init canvas and image
  ctx.canvas.width = this.naturalWidth;
  ctx.canvas.height = this.naturalHeight;
  ctx.drawImage(this, 0, 0);
    
  // gradient using ease-in-out
  var comp = 100;
  var grd = ctx.createLinearGradient(550 - comp, 0, 700 + comp, 0);
  
  for(var t = 0; t <= 1; t += 0.02) {    // convert linear t to "easing" t:
    grd.addColorStop(t, "hsla(360, 100%, 100%, " + easeInOut(t) * 0.8 + ")");
  }
  
  ctx.fillStyle = grd;
  ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height * 0.5);

  // linear (as before)
  var grd = ctx.createLinearGradient(550, 0, 700, 0);
  grd.addColorStop(0, "hsla(360, 100%, 100%, 0)");
  grd.addColorStop(1, "hsla(360, 100%, 100%, 0.8)");
  ctx.fillStyle = grd;
  ctx.fillRect(0,ctx.canvas.height * 0.5+1, ctx.canvas.width, ctx.canvas.height * 0.5);
};

function easeInOut(t) {return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1}

img.src = "//i.imgur.com/ESyzwQg.png";
canvas {width:100%; height:auto}
<canvas></canvas>

查看更多
登录 后发表回答