我有以下代码创建一个矩形,如下图所示:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<p id='one'></p>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 40, 40)
var imgData = ctx.createImageData(100, 100);
var i;
for (i = 0; i < imgData.data.length; i += 16) {
imgData.data[i + 0] = 255;
imgData.data[i + 1] = 0;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 255;
}
// ctx.putImageData(imgData, 10, 10);
</script>
</body>
</html>
当我确保通过不评论ctx.putImageData
添加图像数据时,我只获得如下图所示的图像数据:
如何在红线之间的白色空间中确保图像是在黑色矩形的顶部创建的?
我希望能够看到黑色矩形。我尝试更改alpha通道,但没有做任何事情。
提前致谢:)。
答案 0 :(得分:2)
putImageData
会将目标像素替换为ImageData中包含的像素,无论它们是什么
这意味着如果您的ImageData包含透明像素,一旦您将ImageData放在画布上,这些透明像素就会存在。
有几种方法可以达到你想要的效果。
需要更少代码更改的是从上下文的当前状态进行像素操作。通过调用getImageData
代替createImageData
,您将拥有一个ImageData,其中包含您所选区域中当前绘制的像素。
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 40, 40);
// get the current pixels at (x, y, width, height)
var imgData = ctx.getImageData(10, 10, 100, 100);
var i;
// and do the pixel manip over these pixels
for (i = 0; i < imgData.data.length; i += 16) {
imgData.data[i + 0] = 255;
imgData.data[i + 1] = 0;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 255;
}
ctx.putImageData(imgData, 10, 10);
&#13;
<canvas id="myCanvas"></canvas>
&#13;
主要警告是getImageData
速度较慢,需要的内存比createImageData
更多,所以如果要在动画中的每一帧都这样做,那么它可能不合适。
在这种情况下(动画)的另一个解决方案是使用第二个离屏画布,您将在其上绘制一次ImageData,然后使用drawImage
在主要画布上绘制此离屏画布
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = 'black';
var gridImage = generateGrid(100, 100);
var x = 0;
anim();
/*
Makes your pixel manip on an off-screen canvas
Returns the off-screen canvas
*/
function generateGrid(width, height){
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var off_ctx = canvas.getContext('2d');
var imgData = off_ctx.createImageData(width, height);
for (i = 0; i < imgData.data.length; i += 16) {
imgData.data[i + 0] = 255;
imgData.data[i + 1] = 0;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 255;
}
off_ctx.putImageData(imgData, 0,0);
return canvas;
}
function anim(){
ctx.clearRect(0,0,c.width, c.height);
x = (x + 1) % (c.width + 100);
ctx.fillRect(x, 20, 40, 40);
// and here you draw your generated canvas
ctx.drawImage(gridImage, x - 10, 0);
requestAnimationFrame(anim);
}
&#13;
<canvas id="myCanvas"></canvas>
&#13;
您还可以重构代码,以便在之后绘制ImageData时使普通绘图(此处为fillRect
),但背后当前图纸,这要归功于您的上下文的globalCompositeOperation
属性:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// do first your pixel manip
var imgData = ctx.createImageData(100, 100);
var i;
for (i = 0; i < imgData.data.length; i += 16) {
imgData.data[i + 0] = 255;
imgData.data[i + 1] = 0;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 255;
}
ctx.putImageData(imgData, 10, 10);
// change the gCO to draw behind current non-transparent pixels
ctx.globalCompositeOperation = 'destination-over';
// now make your normal drawings
ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 40, 40);
// reset the gCO
ctx.globalCompositeOperation = 'source-over';
&#13;
<canvas id="myCanvas"></canvas>
&#13;
最后,如果你只定位next-gen browsers,那么你可以使用ImageBitmap object,这将产生与屏幕外画布相同的结果,代码更少:
(async () => {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = 'black';
var gridImage = await generateGrid(100, 100);
var x = 0;
anim();
/*
Makes your pixel manip on an empty ImageData
Returns an Promise resolving to an ImageBitmap
*/
function generateGrid(width, height) {
var imgData = ctx.createImageData(width, height);
for (i = 0; i < imgData.data.length; i += 16) {
imgData.data[i + 0] = 255;
imgData.data[i + 1] = 0;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 255;
}
return createImageBitmap(imgData);
}
function anim() {
ctx.clearRect(0, 0, c.width, c.height);
x = (x + 1) % (c.width + 100);
ctx.fillRect(x, 20, 40, 40);
// and here you draw your generated canvas
ctx.drawImage(gridImage, x - 10, 0);
requestAnimationFrame(anim);
}
})();
&#13;
<canvas id="myCanvas"></canvas>
&#13;
答案 1 :(得分:1)
我无法使用精确的代码,但是当我尝试重叠2张图片时,我设法让它们重叠。
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
</canvas>
<p id = 'one'></p>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = ctx.createImageData(100, 100);
var i;
for (i = 0; i < img.data.length; i += 6) {
img.data[i+0] = 255;
img.data[i+1] = 0;
img.data[i+2] = 0;
img.data[i+3] = 255;
}
var img2 = ctx.createImageData(100, 100);
var i;
for (i = 0; i < img2.data.length; i += 20) {
img2.data[i+0] = 0;
img2.data[i+1] = 255;
img2.data[i+2] = 0;
img2.data[i+3] = 255;
}
var pixels = 4*100*100;
var imgData1 = img.data;
var imgData2 = img2.data;
while (pixels--){
imgData1[pixels] = imgData1[pixels] * 0.5 + imgData2[pixels] *0.5;
}
img.data = imgData1;
ctx.putImageData(img, 10, 0);
</script>