【问题标题】:How to put overlapping images on html5 canvas?如何将重叠图像放在 html5 画布上?
【发布时间】:2020-09-17 12:54:39
【问题描述】:

我想做一个很酷的可视化,在我的画布上重叠许多半透明的图像。为此,我决定使用context.putImageData(),因为这些图像存储为数组。问题是这种方法忽略了画布的实际背景和已经绘制的图像,并计算了相对于白色背景的透明度。

这是一个显示当前行为的 sn-p:

<!DOCTYPE html>
<html>

<body>
<canvas id='cvs' width='100' height='100'></canvas>
</body>
<script>
const size = 50
const context = document.getElementById('cvs').getContext('2d');

const redSquare = context.createImageData(size, size);

for (let i=0; i<size*size*4; i=i+4) {
    redSquare.data[i] = 255;
    redSquare.data[i + 3] = 255; // 1.0 opacity rbga(1, 0, 0, 1)
}

context.putImageData(redSquare, 10, 10);

const trasparentBlackSquare = context.createImageData(size, size);

for (let i=0; i<size*size*4; i=i+4) {
    trasparentBlackSquare.data[i + 3] = 100; // 0.4 opacity rbga(0, 0, 0, 0.4)
}

context.putImageData(trasparentBlackSquare, 30, 30);

</script>

</html>

结果如下所示:

但是,我希望它看起来像这样:

我用两个不同的重叠画布生成了这张图片,这不适合我的问题。

如果有任何解决此问题的方法,请告诉我。

【问题讨论】:

  • 您是想要覆盖源自“普通”图像的图像 - 即 .jpg 或 .png 还是想要覆盖您展示的形状? (我想这只是一个演示,但我不确定)。
  • @A Haworth 是的,我的目标是渲染存储为张量的真实图像。抱歉,演示示例过于简单。

标签: javascript html canvas


【解决方案1】:

如果您将图像写入“工作区”画布,您可以为此浏览图像数据,更改不透明度,就像您为黑色方块所做的那样。然后将其写回工作区画布。然后,您可以使用 drawImage 将其写入主画布。

这是我在我的服务器上尝试的,显然你必须放入一个合适的 img src 以避免 CORS 问题。并且还让 img 和 workspace 元素可见:隐藏 - 我让它们可见以显示正在发生的事情。

<!DOCTYPE html>
<html>

<body>
img
<img id="img" src="https://rgspaces.org.uk/wp-content/uploads/may-morning-in-lockdown-100x100.jpg"/>
cvs
<canvas id='cvs' width='100' height='100'></canvas>
workspace
<canvas id='workspace' width='100' height='100' style="visibility:visible;"></canvas>
</body>
<script>
window.onload=init;
function init() {
  const size = 50
  const cvs = document.getElementById('cvs')
  const context = cvs.getContext('2d');
  const workspace= document.getElementById('workspace')
  const workspacectx=workspace.getContext('2d');
  const img=document.getElementById('img');

  context.fillStyle = 'rgb(255,0,0,1)';
  context.fillRect(10, 10, size, size);

  workspacectx.drawImage(img,20,20,size,size);

  imgdata=workspacectx.getImageData(20, 20, size, size);
  for (var i=0;i<size*size*4;i+=4) {
    imgdata.data[i+3]=150;//if it already has an opacity 0 you would leave it
  }
  workspacectx.putImageData(imgdata,20,20);
  context.drawImage(workspace,20,20);
}
</script>

</html>

【讨论】:

  • 谢谢,我为我的用例实现了它,它按预期工作!但是,通过手动绘制每个像素,我能够获得显着的性能(62 毫秒 vs 205 毫秒)。当您的图像中只有 2 级 alpha 并且您的解决方案似乎克服了这个限制时,我的解决方案有效。再次感谢您的建议!
  • 这很有趣,我会假设 drawImage 以某种方式进行了优化,因此会比逐个像素更快 - 我学到了一些东西。
猜你喜欢
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 2022-12-02
  • 1970-01-01
  • 2012-06-10
  • 2016-11-18
  • 2016-11-15
  • 1970-01-01
相关资源
最近更新 更多