使用drawImage缩放透明图像时出现闪烁



我试图使用CanvasRenderingContext2D.drawImage缩放具有透明像素的图像,但无论何时绘制图像,我最终得到的都是原始大小的图像和画布上绘制的缩放版本。以下是一些重现故障的代码:

<canvas id="cvs" width=200 height=100></canvas>
const canvas = document.getElementById('cvs');
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
const imageData = ctx.createImageData(100, 50);
const data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
if (i % 400 > 360) {
data[i]     = 255;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
}
else {
data[i]     = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 0; // Change this to 255 to get rid of the glitch
}
}
ctx.putImageData(imageData, 0, 0);
ctx.drawImage(canvas, 0, 0, 100, 50, 0, 0, 200, 100);

https://jsfiddle.net/o4sv6qhb/2/

我不明白为什么会发生这种事。如果我不使用任何透明像素,那么问题就消失了。

我想一个解决办法是直接填充最终大小图像的像素,而不是使用drawImage的缩放,但我宁愿不必这样做。

您要在画布上绘制两次,一次使用比例为1:1像素的putImageData,然后再次使用比例为放大版本的drawImage

第二个绘制与第一个重叠,因此如果没有透明像素,则无法看到原始图像,因为它正在被绘制。

但是,如果确实有透明像素,那么较大的图像不会覆盖后面的图像,您可以看到旧图像。

如果只需要drawImage命令中的图像,可以尝试创建一个单独的画布来绘制imageData,然后将该画布绘制到第一个画布上,但要按比例放大。

const canvas = document.getElementById('cvs');
// create a second hidden canvas/context pair
const offscreenCanvas = document.createElement('canvas');
const hiddenContext - offscreenCanvas.getContext('2d');
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
const imageData = ctx.createImageData(100, 50);
const data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
if (i % 400 > 360) {
data[i]     = 255;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
}
else {
data[i]     = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 0; // Change this to 255 to get rid of the glitch
}
}
// draw to the hidden canvas
hiddenContext.putImageData(imageData, 0, 0);
// draw the hidden canvas content to the visible one and scale
ctx.drawImage(offscreenCanvas, 0, 0, 100, 50, 0, 0, 200, 100);

最新更新