我试图在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)
。
在上述方法中如何应用灰度或棕褐色滤镜的任何解决方案。
解决方案中的任何线索都将有所帮助。谢谢
答案 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>
请注意,此代码假定您使用的是现代浏览器,该浏览器确实将鼠标事件限制为帧速率。如果您要定位较旧的浏览器,则可能需要自己进行操作。