在 Canvas 中交换裁剪图像

Swapping Cropped Images in Canvas

我想交换图像中的两个圆形切口并交换它们的位置并将它们绘制到 canvas。但是,我在绘制第二个圆形图像时遇到了问题。有趣的是,在 second 中,如果您取消注释第一行,它会绘制该图像,否则,如果您将它放在函数的末尾,它不会绘制(至少在顶部)。如果我注释掉第一个函数,我就会得到要在 canvas 上绘制的图像。第一个函数总是在第二个函数之前执行。

function first() {
      ctx.drawImage(imgBig, 0, 0);
      ctx.beginPath();
      ctx.arc(imgObj1.x + imgObj1.width / 2, imgObj1.y + imgObj1.width / 2, imgObj1.width / 2, 0, 6.28, false);
      ctx.clip();
      ctx.stroke(); // the outline of circle
      ctx.closePath();
      ctx.drawImage(imgBig, imgObj2.x, imgObj2.y, imgObj2.width, imgObj2.height, imgObj1.x, imgObj1.y, imgObj1.width, imgObj1.height);

function second() {
      // ctx.drawImage(imgCuttingBoard, 0, 0); // this will draw over canvas
      ctx.beginPath();
      ctx.arc(imgObj2.x + imgObj2.width / 2, imgObj2.y + imgObj2.width / 2, imgObj2.width / 2, 0, 6.28, false);
      ctx.clip();
      ctx.closePath();
      ctx.drawImage(imgCuttingBoard, imgObj1.x, imgObj1.y, imgObj1.width, imgObj1.height, imgObj2.x, imgObj2.y,
      imgObj2.width, imgObj2.height); // this doesn't draw on top of the image (might be drawing underneath?)
      // ctx.drawImage(imgCuttingBoard, 0, 0); // this will not draw over canvas here
}  

假设您在尝试 drawImage 之前给了图像完全加载的时间。您确实使用了 image.onload 并等待图像加载?

那么你的问题很可能是剪裁...

context.clip是累积的。如果将一个剪辑 (clip#1) 应用到 canvas,然后再应用另一个剪辑 (clip#2),则生成的剪辑区域是 clip#1 和 clip#2 的交集。生成的剪辑不是剪辑#2。

因此,如果您想撤消剪辑 #1 以便使用完整的剪辑 #2,则必须将第一个剪辑包装在 context.savecontext.restore 中。

这里有一个稍微不同的方法,使用临时 canvas

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/faces%20no%20background.png";
function start(){
    cw=canvas.width=img.width;
    ch=canvas.height=img.height;
    ctx.drawImage(img,0,0);
    // do the swap
    clipCircle(img,63.5,56,54,203,177);
    clipCircle(img,203,177,54,63.5,56);
}

function clipCircle(img,sourceCX,sourceCY,r,newCX,newCY){
    var c=document.createElement('canvas');
    var cctx=c.getContext('2d');
    c.width=2*r;
    c.height=2*r;
    
    // define an clipping circle 
    cctx.beginPath();
    cctx.arc(r,r,r,0,Math.PI*2);
    // draw the source into the temp canvas
    cctx.drawImage(img,-sourceCX+r,-sourceCY+r);
    // draw the temp canvas onto the main canvas
    ctx.drawImage(c,newCX-r,newCY-r);
}
body{ background-color: ivory; }
canvas{border:1px solid red; margin:0 auto; }
<h4>Swapped clipping on canvas<br>(top-left swapped with bottom-center)</h4>
<canvas id="canvas" width=300 height=300></canvas>
<h4>Original Image</h4>
<img src='https://dl.dropboxusercontent.com/u/139992952/multple/faces%20no%20background.png'>