我有两幅画布,让我们说Canvas A和Canvas B.用户上传一个文件然后放到Canvas A上,我已经做过了。一旦发生这种情况,我想开始将Canvas A的部分复制到Canvas B。
我试过这样做
source = a.getContext('2d');
b.drawImage(source, 0, 0, source.width, source.height);
但是复制整件事。所以我的问题是,如何将Canvas A的一部分复制到Canvas B。
编辑:
我也试过......
var imgData=atx.getImageData(10,10,20,20);
btx.putImageData(imgData, 0, 0);
但只是将imgData复制回Canvas A at(0,0)。
答案 0 :(得分:1)
首先,b.drawImage
将CanvasImageSource
作为其第一个参数,而不是上下文。将整个HTMLCanvasElement
传递到那里。
drawImage
需要九个参数,而你需要全部这些参数。如果您只使用五个,则假定您正在拍摄整个源图像并将其绘制到目的地。完整的签名是
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
sx
,sy
,sw
和sh
定义您要从源中复制的矩形。 dx
,dy
,dw
和dh
定义了您在目的地吸引的矩形。请注意,sw
和sh
不得与dw
和dh
匹配。如果源矩形和目标矩形不具有相同的大小,则复制的图像将被压扁或拉伸以适合目标矩形。
我制作了一个片段,让您可以与drawImage
一起玩,看看它在做什么。当您将其视为整页时效果最佳:
const srcCanvas = document.querySelector('#source');
const srcContext = srcCanvas.getContext('2d');
const destContext = document.querySelector('#destination')
.getContext('2d');
// The overlay canvas is where we draw the red rectangle. It's
// positioned directly on top of the source canvas.
const overlay = document.querySelector('#overlay')
.getContext('2d');
overlay.fillStyle = 'rgba(255, 0, 0, 0.3)';
overlay.strokeStyle = 'red';
const inputs = Array.from(
document.querySelectorAll('input[type="number"]')
);
const lockScale = document.querySelector('#lockScale');
lockScale.addEventListener('change', () => {
inputs[6].disabled = lockScale.checked;
inputs[7].disabled = lockScale.checked;
if (lockScale.checked) update();
});
// Grab an image and draw it on the source canvas...
fetch('https://picsum.photos/320/240/?image=451')
.then(res => res.blob())
.then(createImageBitmap)
.then(bitmap => {
srcContext.drawImage(bitmap, 0, 0);
// ...and only then start watching for changes in the input boxes.
// There's no point in spending cycles copying an empty canvas.
inputs.forEach(i => {
i.addEventListener('input', update);
});
update();
});
function update() {
if (lockScale.checked) {
inputs[6].value = inputs[2].value;
inputs[7].value = inputs[3].value;
}
const values = inputs.map(i => Number(i.value));
destContext.clearRect(0, 0, 320, 240);
overlay.clearRect(0, 0, 320, 240);
overlay.beginPath();
overlay.rect(
// These adjustments move the overlay path off the boundary
// between pixels so the rectangle border is a crisp 1px line.
values[0] + 0.5,
values[1] + 0.5,
// JavaScript uses half-open intervals, which makes sense for
// code. But for a visualization of graphics work, fully-
// closed intervals are preferable. These adjustments make the
// overlay rectangle exactly cover the pixels that will be
// copied.
values[2] - 1,
values[3] - 1
);
overlay.fill();
overlay.stroke();
// The real drawing code of this snippet doesn't look like the
// code you would actually use. We call apply() on drawImage()
// so we can pass in the entire values array without listing out
// every element.
destContext.drawImage.apply(
destContext, // We don't want to change what 'this' points to
[srcCanvas].concat(values));
// The spread operator provides a more elegant way of doing this:
// destContext.drawImage(srcCanvas, ...values);
// But it doesn't work with IE.
}

canvas {
height: 240px;
width: 320px;
position: absolute;
top: 0;
left: 0;
}
.canvasbox {
display: inline-block;
position: relative;
width: 320px;
height: 240px;
border: 1px solid black;
}
input[type="number"] {
font-family: monospace;
border: none;
background: silver;
color: black;
width: 3em;
}
input[disabled] {
color: silver;
background: grey;
}
code {
color: navy;
}

<div class="canvasbox">
<canvas id="source" width="320" height="240"></canvas>
<canvas id="overlay" width="320" height="240"></canvas>
</div>
<div class="canvasbox">
<canvas id="destination" width="320" height="240"></canvas>
</div>
<div>
<code>
destContext.drawImage(srcCanvas,
<input id="sx" type="number" value="180">,
<input id="sy" type="number" value="100">,
<input id="sw" type="number" value="40">,
<input id="sh" type="number" value="50">,
<input id="dx" type="number" value="10">,
<input id="dy" type="number" value="10">,
<input id="dw" type="number" value="40">,
<input id="dh" type="number" value="50">);
</code>
</div>
<div>
<label>
<input id="lockScale" type="checkbox">Lock scale
</label>
</div>
&#13;