gpt4 book ai didi

javascript - JavaScript Canvas 中透明框后面的模糊

转载 作者:行者123 更新时间:2023-11-28 17:29:57 39 4
gpt4 key购买 nike

如何在 JavaScript Canvas 中实现透明框 (fillStyle = 'rgba(255, 255, 255, 0.2)') 后面的模糊效果?这是我到目前为止所得到的:

var canvas = document.getElementById('draw');
var c = canvas.getContext('2d');

function main() {
c.fillStyle = '#222';
c.fillRect(0, 0, canvas.width, canvas.height);

c.fillStyle = '#000';
c.fillRect(32, 32, 64, 64);
c.fillStyle = 'rgba(255, 255, 255, 0.2)';
c.filter = 'blur(5px)';
c.fillRect(16, 16, 128, 24);
}

但是发生的情况是,矩形本身被模糊了,而不是模糊了矩形后面的背景,这很明显。

Blurred rectangle

在最终脚本中,我可能会使用路径而不是矩形。

最佳答案

Context2D 滤镜将仅应用于您的新绘图,因此为了模糊背景,您实际上必须重新绘制想要模糊的背景部分。

幸运的是,canvas 可以自己绘制图像。

var blurredRect = {
x: 80,
y: 80,
height: 200,
width: 200,
spread: 10
};
var ctx = canvas.getContext('2d');

var img = new Image();
img.onload = draw;
img.src = 'https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg';

function draw() {
canvas.width = img.width / 2;
canvas.height = img.height / 2;
// first pass draw everything
ctx.drawImage(img, 0,0, canvas.width, canvas.height);
// next drawings will be blurred
ctx.filter = 'blur('+ blurredRect.spread +'px)';
// draw the canvas over itself, cropping to our required rect
ctx.drawImage(canvas,
blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height,
blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height
);
// draw the coloring (white-ish) layer, without blur
ctx.filter = 'none'; // remove filter
ctx.fillStyle = 'rgba(255,255,255,0.2)';
ctx.fillRect(blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height);
}
<canvas id="canvas"></canvas>

但是, Canvas 模糊过滤器与CSS过滤器有点不同,因为它会使扩散停留在绘制区域内。这意味着在我们的例子中,我们的矩形周围有一个 5px 的边框,它比中心的模糊程度要低。

要解决此问题,我们可以以不同的顺序处理整个事情并使用 globalCompositeOperation属性*:

var blurredRect = {
x: 80,
y: 80,
height: 200,
width: 200,
spread: 10
};
var ctx = canvas.getContext('2d');

var img = new Image();
img.onload = draw;
img.src = 'https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg';

function draw() {
var spread = blurredRect.spread,
ratio = 0.5,
// make our blurred rect spreads
x = blurredRect.x - spread,
y = blurredRect.y - spread,
w = blurredRect.width + (spread * 2),
h = blurredRect.height + (spread * 2);

canvas.width = img.width * ratio;
canvas.height = img.height * ratio;

// this time we will first draw the blurred rect
ctx.filter = 'blur('+ spread +'px)';
// this time we draw from the img directly
ctx.drawImage(img,
x / ratio, y / ratio, w / ratio, h / ratio,
x, y, w, h
);

// now we will want to crop the resulting blurred image to the required one, so we get a clear-cut

ctx.filter = 'none'; // remove filter
// with this mode, previous drawings will be kept where new drawings are made
ctx.globalCompositeOperation = 'destination-in';
ctx.fillStyle = '#000'; // make it opaque
ctx.rect(blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height);
ctx.fill(); // clear-cut done
// reuse our rect to make the white-ish overlay
ctx.fillStyle = 'rgba(255,255,255,0.2)';
// reset gCO to its default
ctx.globalCompositeOperation = 'source-over';
ctx.fill();

// now we will draw behind the our blurred rect
ctx.globalCompositeOperation = 'destination-over';
ctx.drawImage(img, 0,0, canvas.width, canvas.height);

// reset to defaults
ctx.globalCompositeOperation = 'source-over';
}
<canvas id="canvas"></canvas>

但是这种方法要求我们将整个背景作为可绘制的东西进行访问,在上面的示例中这只是一个图像,但在现实生活中,这可能意味着您必须在第二个屏幕外执行此操作 Canvas 。

var blurredRect = {
x: 80,
y: 80,
height: 200,
width: 200,
spread: 2
};
var ctx = canvas.getContext('2d');
// create an off-screen canvas
var bCanvas = canvas.cloneNode();
var bCtx = bCanvas.getContext('2d');

var img = new Image();
img.onload = draw;
img.src = 'https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg';

function draw() {
var spread = blurredRect.spread;

canvas.width = bCanvas.width = img.width / 2;
canvas.height = bCanvas.height = img.height / 2;

// now we have a composed background
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.font = '40px Impact';
ctx.fillStyle = 'white';
ctx.fillText('..SO BLUR ME..', 120, 282);

// make our clear-cut on the offscreen canvas
bCtx.filter = 'blur(' + spread +'px)';
bCtx.drawImage(canvas,
blurredRect.x - spread, blurredRect.y - spread, blurredRect.width + spread * 2, blurredRect.height + spread * 2,
blurredRect.x - spread, blurredRect.y - spread, blurredRect.width + spread * 2, blurredRect.height + spread * 2
);
// clear-cut
bCtx.filter = 'none';
bCtx.globalCompositeOperation = 'destination-in';
bCtx.beginPath();
bCtx.rect(blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height);
bCtx.fillStyle = '#000';
bCtx.fill();
// white-ish layer
bCtx.globalCompositeOperation = 'source-over';
bCtx.fillStyle = 'rgba(255,255,255,0.2)';
bCtx.fillRect(blurredRect.x, blurredRect.y, blurredRect.width, blurredRect.height);

// now just redraw on the visible canvas
ctx.drawImage(bCanvas, 0,0);

}
<canvas id="canvas"></canvas>

<小时/>

*有人可能会说,我们可以使用 ctx.clip() 来代替屏幕外 Canvas 和 gCO,但既然你说它可能是比矩形更复杂的路径,我不会建议这样做。事实上,虽然它需要更少的代码,并且可能使用更少的内存,但剪切对于抗锯齿来说很糟糕,而且由于您正在进行模糊处理,所以看起来会很丑陋。

关于javascript - JavaScript Canvas 中透明框后面的模糊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50687334/

39 4 0
文章推荐: python - 将文本格式的数据读入 Python Pandas 数据框
文章推荐: html - 在 div 中居中 div
文章推荐: html - 调整图像大小以占据整个
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com