画布形状内部阴影+混合模式



所以这几天一直让我发疯。

我正在尝试使用不同的混合模式(如overlay(在JS中复制Photoshop的内部阴影。

有一些简单的方法可以为形状添加阴影,如ctx.shadowBlurctx.filter = 'drop-shadow(...)',但这些只会生成外部阴影。您可以使用一些合成魔术创建内部阴影xor,但这会使图像边缘不平滑(我猜xor不能很好地处理抗锯齿(,如以下示例所示:

https://jsfiddle.net/89pes8ap/1/

所以,我有另一个可行的想法,因为它只用过一次xor

https://jsfiddle.net/3cnwtvyj/

但正如你所看到的,overlay-ed版本仍然没有平滑的边缘。

所以,我的问题是:如何添加具有不同混合模式的平滑内部阴影,以适应各种形状?

复合操作确实适用于 alpha 通道,因此不适合阴影。

不幸的是,我认为对于透明背景上的阴影,以及一个圆圈,您无能为力。

我可以看到的一件小事是,您实际上不需要异或部分,并且可以将其替换为由矩形和弧组成的路径,您将填充为"偶数"。这将直接创建孔,减少一点抗锯齿伪影。

drawOP();
drawEvenOdd();
function drawEvenOdd() {
let canvas = document.getElementById('evenodd');
canvas.width = 150;
canvas.height = 200;
let ctx = canvas.getContext('2d')
ctx.textAlign = 'center';
ctx.shadowColor = 'black';
ctx.shadowBlur = 10 * 2;
ctx.shadowOffsetY = 5;
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
// will draw an hole
ctx.fill('evenodd');
// remove shadow
ctx.shadowColor = 'transparent';
ctx.shadowBlur = ctx.shadowOffsetY = 0;
ctx.globalCompositeOperation = 'destination-out';
ctx.fill('evenodd');
ctx.globalCompositeOperation = 'source-over';
ctx.fillText('evenodd', 100, 180)
}
function drawOP() {
let canvas = document.getElementById('OP')
canvas.width = 150;
canvas.height = 200;
let ctx = canvas.getContext('2d')
ctx.textAlign = 'center';
ctx.fillStyle = 'black'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.globalCompositeOperation = 'xor'
ctx.arc(100, 100, 50, 0, 2 * Math.PI)
ctx.fill()
ctx.filter = 'drop-shadow(0 5px 10px black)'
ctx.drawImage(canvas, 0, 0)
ctx.filter = 'none';
ctx.fillText('OP', 100, 180)
}
<canvas id="OP"></canvas>
<canvas id="evenodd"></canvas>

最新更新