在mousemove上应用灰度和棕褐色滤镜-画布

时间:2019-12-12 08:42:22

标签: javascript image-processing canvas html5-canvas

我试图在mouseMove时在画布上应用灰度和棕褐色滤镜。 我正在使用CanvasRenderingContext2D.filter来应用过滤器。 这是示例代码

var radgrad = this.ctx.createRadialGradient(x, y, 50 / 8, x, y, 50 / 2);
radgrad.addColorStop(0, 'rgb(0, 0, 0)');
radgrad.addColorStop(1, 'rgb(0, 0, 0, 1)');

this.ctx.filter = "grayscale(100%) blur(5px) opacity(50%)";
this.ctx.fillStyle = radgrad;
this.ctx.beginPath();
this.ctx.arc(x, y, 50, 0, Math.PI * 2);
this.ctx.fill();

问题是当我尝试应用灰度时无法实现它,但是正在应用blur(5px)

在上述方法中如何应用灰度或棕褐色滤镜的任何解决方案。

Here's a sample fiddle

解决方案中的任何线索都将有所帮助。谢谢

1 个答案:

答案 0 :(得分:1)

我不清楚您想要什么,所以我假设您想要累积一些东西,因为两次移至同一位置将两次应用滤镜。

为此,最简单的方法是从您的图像中创建一个CanvasPattern。这样,您就可以使用该图像作为fillStyle来填充子路径,同时在此新图形上应用滤镜:

const img = new Image();
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/1024px-Sunset_2007-1.jpg";
img.onload = begin;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
const rad = 25;

function begin() {
  canvas.width = img.width;
  canvas.height = img.height;
  // first draw the original image
  ctx.drawImage( img, 0, 0 );
  // create a CanvasPattern from it
  const patt = ctx.createPattern(img, 'no-repeat');
  // set the fillStyle to this pattern
  ctx.fillStyle = patt;
  // and the filter
  ctx.filter = "grayscale(100%) blur(5px) opacity(50%)";
  // now at each mousemove
  document.onmousemove = e => {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    // we just draw a new arc
    ctx.beginPath();
    ctx.arc( x, y, rad, 0, Math.PI * 2 );
    // this will use the filtered pattern
    ctx.fill();
  };
}
<canvas id="canvas"></canvas>

如果您不希望它是累积性的(例如刮刮卡),则可以创建一个大的子路径并在每一帧重新绘制所有内容。

const img = new Image();
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/1024px-Sunset_2007-1.jpg";
img.onload = begin;
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
const rad = 25;
const points = [];
const filter = "grayscale(100%) blur(5px) opacity(50%)";

function begin() {
  canvas.width = img.width;
  canvas.height = img.height;

  const patt = ctx.createPattern(img, 'no-repeat');
  ctx.fillStyle = patt;
  
  draw();

  // now at each mousemove
  document.onmousemove = e => {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    // store that point
    points.push( { x, y } );
    // and redraw
    draw();
  };
}
function draw() {
  // remove the filter
  ctx.filter = "none";
  // so we can draw the background untouched
  ctx.drawImage( img, 0, 0 );
  // we'll now compose a big sub-path
  ctx.beginPath();
  points.forEach( ({ x, y }) => {
    ctx.moveTo( x, y );
    ctx.arc( x, y, rad, 0, Math.PI * 2 )
  });
  // with the filter
  ctx.filter = filter;
  ctx.fill();
}
<canvas id="canvas"></canvas>

请注意,此代码假定您使用的是现代浏览器,该浏览器确实将鼠标事件限制为帧速率。如果您要定位较旧的浏览器,则可能需要自己进行操作。