使用 Clip 函数在画布上使用 JavaScript 实现渐变效果

pra*_*ect 0 html javascript canvas

我正在尝试使用clip()画布中的函数来创建这种效果,如图所示:有一个背景图像,当鼠标悬停在其上时,会显示部分图像。我让它作为一个圆圈工作,但我想要这种渐变效果,你可以看到图片。我该如何实现这一目标?

<!DOCTYPE HTML>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="./assets/stylesheet/normalize.css">
    <link rel="stylesheet" type="text/css" href="./assets/stylesheet/style.css">
  </head>
  <body>
    <canvas id="canvas" width="2000" height="1200"></canvas>
    <script>
      var can = document.getElementById('canvas');
      var ctx = can.getContext('2d');

      can.addEventListener('mousemove', function(e) {
          var mouse = getMouse(e, can);
          redraw(mouse);
      }, false);

      function redraw(mouse) {
          console.log('a');
          can.width = can.width;
          ctx.canvas.width = window.innerWidth;
          ctx.canvas.height = window.innerHeight;
          ctx.drawImage(img, 0, 0);
          ctx.beginPath();
          ctx.rect(0,0,2000,1200);
          ctx.arc(mouse.x, mouse.y, 200, 0, Math.PI*2, true)
          ctx.clip();
          ctx.fillRect(0,0,2000,1200);
    }

      var img = new Image();
      img.onload = function() {
          redraw({x: 0, y: 0})
      }

      img.src = 'http://placekitten.com/2000/1000';

      function getMouse(e, canvas) {
          var element = canvas,
          offsetX = 0,
          offsetY = 0,
          mx, my;

      // Compute the total offset. It's possible to cache this if you want
      if (element.offsetParent !== undefined) {
          do {
              offsetX += element.offsetLeft;
              offsetY += element.offsetTop;
          } while ((element = element.offsetParent));
      }

      mx = e.pageX - offsetX;
      my = e.pageY - offsetY;

      return {
          x: mx,
          y: my
      };
  }
</script>
Run Code Online (Sandbox Code Playgroud)

我想要的效果

Bli*_*n67 5

使用径向渐变

有很多方法可以做到这一点,但最简单的是带有 alpha 的渐变。

首先,您需要定义要显示的圆圈的大小。

var cirRadius = 300;
Run Code Online (Sandbox Code Playgroud)

然后是该圆的中心位置(画布坐标)

var posX = 100;
var posY = 100;
Run Code Online (Sandbox Code Playgroud)

现在定义 RGB 颜色

var RGB = [0,0,0] ; // black
Run Code Online (Sandbox Code Playgroud)

然后是一组 alpha 值来定义什么是透明的

var alphas = [0,0,0.2,0.5,1]; // zero is transparent;
Run Code Online (Sandbox Code Playgroud)

现在您要做的就是渲染背景图像

// assume ctx is context and image is loaded
ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height); // fill the canvas
Run Code Online (Sandbox Code Playgroud)

然后创建渐变,使其以您想要的位置为中心,第二个圆以您想要的半径为中心。前 3 个数字定义渐变起点的中心和半径,后 3 个数字定义渐变终点的中心和半径

var grad = ctx.createRadialGradient(posX,posY,0,posX,posY,cirRadius);
Run Code Online (Sandbox Code Playgroud)

现在使用 CSS 颜色字符串添加颜色停止点rgba(255,255,255,1),其中最后一个是从 0 到 1 的 alpha 值。

var len = alphas.length-1;
alphas.forEach((a,i) => {
     grad.addColorStop(i/len,`rgba(${RGB[0]},${RGB[1]},${RGB[2]},${a})`);
});
Run Code Online (Sandbox Code Playgroud)

或者对于不支持箭头函数或模板字符串的旧版浏览器

var i,len = alphas.length;
for(i = 0; i < len; i++){
     grad.addColorStop(i / (len - 1), "rgba(" + RGB[0] + "," + RGB[1] + "," + RGB[2] + "," + alphas[i] + ")");

}
Run Code Online (Sandbox Code Playgroud)

然后将填充样式设置为渐变

ctx.fillStyle = grad;
Run Code Online (Sandbox Code Playgroud)

然后填充一个覆盖图像的矩形

ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);
Run Code Online (Sandbox Code Playgroud)

你就完成了。

通过鼠标事件设置位置,然后使用每秒 60 次执行上述步骤,window.requestAnimationFrame您可以实时获得您想要的效果。

这是一个例子