画布中是否可以将黑/白蒙版转换为黑/透明蒙版? 我到处搜索,唯一的方法是使用像素操作,太慢了。
基本上我想要这个转变:
var ac = a.getContext('2d');
var g = ac.createLinearGradient(25, 0, 75, 0);
g.addColorStop(0, 'black');
g.addColorStop(1, 'white');
ac.fillStyle = 'white';
ac.fillRect(0, 0, 100, 100);
ac.fillStyle = g;
ac.fillRect(25, 25, 50, 50);
var bc = b.getContext('2d');
var g = bc.createLinearGradient(25, 0, 75, 0);
g.addColorStop(0, 'black');
g.addColorStop(1, '#00000000');
bc.fillStyle = g;
bc.fillRect(25, 25, 50, 50);
body {
background-color: pink;
}
canvas {
outline: 1px solid cyan;
}
Convert this:<canvas id="a" width="100" height="100"></canvas>
to this:<canvas id="b" width="100" height="100"></canvas>
我得到的最接近的是使用乘法:
var a = document.getElementById('a'),
m = document.getElementById('m'),
c = document.getElementById('c');
// green image
a.context = a.getContext('2d');
a.context.fillStyle = 'green';
a.context.fillRect(0, 0, 100, 100);
// black and white mask
m.context = m.getContext('2d');
m.context.fillStyle = 'white';
m.context.fillRect(0, 0, 100, 100);
var g = m.context.createLinearGradient(25, 0, 75, 0);
g.addColorStop(0, 'black');
g.addColorStop(1, 'white');
m.context.fillStyle = g;
m.context.fillRect(25, 25, 50, 50);
// result
c.context = c.getContext('2d');
c.context.drawImage(a, 0, 0);
c.context.globalCompositeOperation = "multiply";
c.context.drawImage(m, 0, 0);
body {
background-color: cyan;
}
Green image:
<canvas id="a" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
Black and white mask:
<canvas id="m" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
Result:
<canvas id="c" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
但问题在于,没有中间步骤可以让我访问黑色/透明画布。
最好的方法是按照您需要使用的方式准备您的资产。
因此,如果可能的话,根本不要生成或存储不透明渐变。
现在,我毫不怀疑这可能无法在所有情况下实现......
SVG
luminanceToAlpha
上有
<feColorMatrix>
效果,您也可以在 2D 画布中使用该效果。它将所有低亮度的像素转换为透明像素,将高亮度的像素转换为不透明的黑色,这与您想要的相反,因为在渐变上,白色像素将变为黑色,黑色像素将变为透明。
所以我们需要先反转渐变,然后应用 luminanceToAlpha
:
var a = document.getElementById('a'),
m = document.getElementById('m'),
c = document.getElementById('c');
// green image
a.context = a.getContext('2d');
a.context.fillStyle = 'green';
a.context.fillRect(0, 0, 100, 100);
// black and white mask
m.context = m.getContext('2d');
m.context.fillStyle = 'white';
m.context.fillRect(0, 0, 100, 100);
var g = m.context.createLinearGradient(25, 0, 75, 0);
g.addColorStop(0, 'black');
g.addColorStop(1, 'white');
m.context.fillStyle = g;
m.context.fillRect(25, 25, 50, 50);
// result
c.context = c.getContext('2d');
c.context.drawImage(a, 0, 0);
c.context.filter = "invert(1) url(#lumToAlpha)";
c.context.drawImage(m, 0, 0);
body {
background-color: cyan;
}
Green image:
<canvas id="a" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
Black and white mask:
<canvas id="m" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
Result:
<canvas id="c" width=100 height=100 style="outline: 1px solid cyan;"></canvas>
<svg width="0" height="0" style="position:absolute">
<filter id="lumToAlpha"><feColorMatrix type="luminanceToAlpha"/></filter>
</svg>
这种方法有一个很大的缺点:Safari 还不支持 2D 画布的
filter
。他们终于正在研究它,在切换一些标志后甚至可以在最新的技术预览中进行测试,但它还不稳定,因此对于大多数 iPhone 用户来说,您需要回退到 ImageData
操作。filter
在您未设置时是否返回 "none"
。
const supportsCanvasFilters = new OffscreenCanvas(1,1).getContext("2d").filter==="none";