仅绘制来自其他两个 canvas 的 canvas 上的重叠像素
Draw only overlapping pixels on a canvas from two other canvasses
我有 2 个相同的画布,我用鼠标在上面绘制,还有第 3 个(仍然相同的宽度和高度),我想通过只显示重叠像素来获得其他 2 个的 'combination' , 表示与最初的 2 个画布具有相同坐标的那些。
类似于:
const left = document.querySelector('#canvasLeft');
const right = document.querySelector('#canvasRight');
const combined = document.querySelector('#canvasCombined');
const draw = () => {
// do drawing on each canvas...
// get image data from the canvasses...
const imageDataRight = right.ctx.getImageData(0, 0, right.canvas.width, right.canvas.height);
const imageDataLeft = left.ctx.getImageData(0, 0, left.canvas.width, left.canvas.height);
// do something with the image data picking only the matching pixels from each canvas --> PLEASE HELP!
combined.ctx.putImageData(imageDataCombined, 0, 0);
}
更新:请参阅下图,更好地解释我要实现的目标
我相信你想要的是异或复合模式的反面。您应该通过在“正常”复合模式下将 2 个画布绘制到第 3 个画布中来获得所需的结果。然后再异或模式绘制。
let canvas1 = document.getElementById("canvas1");
let canvas2 = document.getElementById("canvas2");
let canvas3 = document.getElementById("canvas3");
let c1 = canvas1.getContext("2d");
let c2 = canvas2.getContext("2d");
let c3 = canvas3.getContext("2d");
// Draw into canvas1
c1.fillStyle = "#000000";
c1.beginPath();
c1.fillRect(0, 0, 60, 60);
c1.stroke();
// Draw into canvas2
c2.fillStyle = "#000000";
c2.beginPath();
c2.fillRect(40, 40, 60, 60);
c2.stroke();
// Reset composite mode to default
c3.globalCompositeOperation = 'source-over';
// Draw 1 and 2 into 3
c3.drawImage(canvas1, 0, 0);
c3.drawImage(canvas2, 0, 0);
// Turn on xor
c3.globalCompositeOperation = 'xor';
// Draw 1 and 2 into 3 again
c3.drawImage(canvas1, 0, 0);
c3.drawImage(canvas2, 0, 0);
canvas {
border: 1px solid red;
}
<canvas id="canvas1" width="100" height="100"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<canvas id="canvas3" width="100" height="100"></canvas>
我用一个圆圈试了一下,它在圆角线上的抗锯齿方面有问题。所以这是使用图像数据的另一种方式。
let canvas1 = document.getElementById("canvas1");
let canvas2 = document.getElementById("canvas2");
let canvas3 = document.getElementById("canvas3");
let c1 = canvas1.getContext("2d");
let c2 = canvas2.getContext("2d");
let c3 = canvas3.getContext("2d");
// Draw into canvas1
c1.beginPath();
c1.fillRect(0, 0, 60, 60);
c1.stroke();
// Draw into canvas2
c2.beginPath();
c2.arc(60, 60, 20, 0, 2 * Math.PI, false);
c2.fill();
c2.lineWidth = 1;
c2.stroke();
var data1 = c1.getImageData(0, 0, 100, 100);
var data2 = c2.getImageData(0, 0, 100, 100);
var data3 = c3.getImageData(0, 0, 100, 100);
for (let pixel = 0; pixel < data3.data.length; pixel += 4) {
if (data1.data[pixel+3] > 0 && data2.data[pixel+3] > 0) {
data3.data[pixel] = 0;
data3.data[pixel+1] = 0;
data3.data[pixel+2] = 0;
data3.data[pixel+3] = 255;
}
}
c3.putImageData(data3, 0, 0);
canvas {
border: 1px solid red;
}
<canvas id="canvas1" width="100" height="100"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<canvas id="canvas3" width="100" height="100"></canvas>
我有 2 个相同的画布,我用鼠标在上面绘制,还有第 3 个(仍然相同的宽度和高度),我想通过只显示重叠像素来获得其他 2 个的 'combination' , 表示与最初的 2 个画布具有相同坐标的那些。
类似于:
const left = document.querySelector('#canvasLeft');
const right = document.querySelector('#canvasRight');
const combined = document.querySelector('#canvasCombined');
const draw = () => {
// do drawing on each canvas...
// get image data from the canvasses...
const imageDataRight = right.ctx.getImageData(0, 0, right.canvas.width, right.canvas.height);
const imageDataLeft = left.ctx.getImageData(0, 0, left.canvas.width, left.canvas.height);
// do something with the image data picking only the matching pixels from each canvas --> PLEASE HELP!
combined.ctx.putImageData(imageDataCombined, 0, 0);
}
更新:请参阅下图,更好地解释我要实现的目标
我相信你想要的是异或复合模式的反面。您应该通过在“正常”复合模式下将 2 个画布绘制到第 3 个画布中来获得所需的结果。然后再异或模式绘制。
let canvas1 = document.getElementById("canvas1");
let canvas2 = document.getElementById("canvas2");
let canvas3 = document.getElementById("canvas3");
let c1 = canvas1.getContext("2d");
let c2 = canvas2.getContext("2d");
let c3 = canvas3.getContext("2d");
// Draw into canvas1
c1.fillStyle = "#000000";
c1.beginPath();
c1.fillRect(0, 0, 60, 60);
c1.stroke();
// Draw into canvas2
c2.fillStyle = "#000000";
c2.beginPath();
c2.fillRect(40, 40, 60, 60);
c2.stroke();
// Reset composite mode to default
c3.globalCompositeOperation = 'source-over';
// Draw 1 and 2 into 3
c3.drawImage(canvas1, 0, 0);
c3.drawImage(canvas2, 0, 0);
// Turn on xor
c3.globalCompositeOperation = 'xor';
// Draw 1 and 2 into 3 again
c3.drawImage(canvas1, 0, 0);
c3.drawImage(canvas2, 0, 0);
canvas {
border: 1px solid red;
}
<canvas id="canvas1" width="100" height="100"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<canvas id="canvas3" width="100" height="100"></canvas>
我用一个圆圈试了一下,它在圆角线上的抗锯齿方面有问题。所以这是使用图像数据的另一种方式。
let canvas1 = document.getElementById("canvas1");
let canvas2 = document.getElementById("canvas2");
let canvas3 = document.getElementById("canvas3");
let c1 = canvas1.getContext("2d");
let c2 = canvas2.getContext("2d");
let c3 = canvas3.getContext("2d");
// Draw into canvas1
c1.beginPath();
c1.fillRect(0, 0, 60, 60);
c1.stroke();
// Draw into canvas2
c2.beginPath();
c2.arc(60, 60, 20, 0, 2 * Math.PI, false);
c2.fill();
c2.lineWidth = 1;
c2.stroke();
var data1 = c1.getImageData(0, 0, 100, 100);
var data2 = c2.getImageData(0, 0, 100, 100);
var data3 = c3.getImageData(0, 0, 100, 100);
for (let pixel = 0; pixel < data3.data.length; pixel += 4) {
if (data1.data[pixel+3] > 0 && data2.data[pixel+3] > 0) {
data3.data[pixel] = 0;
data3.data[pixel+1] = 0;
data3.data[pixel+2] = 0;
data3.data[pixel+3] = 255;
}
}
c3.putImageData(data3, 0, 0);
canvas {
border: 1px solid red;
}
<canvas id="canvas1" width="100" height="100"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<canvas id="canvas3" width="100" height="100"></canvas>