Canvas'Clip'反向动作?

时间:2011-01-27 20:49:06

标签: html5 canvas clip

假设我有:

var context = document.getElementById('test').getContext('2d');

// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);

// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
context.closePath();

context.globalCompositeOperation = 'destination-out';

// 'P' hole
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.fillStyle = '#ffffff';
context.fill();
context.closePath();

这是有效的,除非你可以看到'洞'不是剪辑,所以如果背景不是实心,你根本无法设置洞的'填充'颜色以匹配背景。 / p>

因此我需要修剪这个洞。然而,当我这样做时,显示的'P'的唯一部分是由剪辑'孔'限定的部分。我需要反过来。我需要显示“P”,但是用“洞”剪切部分,这样任何背景都会显示出来。

据我所知,但不完全存在:

var context = document.getElementById('test').getContext('2d');

// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);

// 'P' hole clip
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.clip();
context.closePath();

// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
context.closePath();

感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

我知道你刚才问过这个问题,但我有一个答案。

你的第一个例子是半正确的。使用目标输出将起作用,但是为了不打扰您想要绘制的画布,我们创建一个新画布并将其绘制在其中。

然后,一旦我们用切口绘制了我们的形状,我们就将整个画布绘制到原始画布上。由于新画布没有背景,因此它将保持透明度。

var canvas = document.getElementById('test'),
    context = canvas.getContext('2d'),

    // New canvas - we will draw the letter P on here
    newCanvas = document.createElement('canvas'),
    newContext = newCanvas.getContext('2d');

// Make sure you have enough room on your new canvas
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;

with(newContext) {
    // 'P'
    beginPath();
    moveTo(90,89);
    lineTo(161,89);
    quadraticCurveTo(200,89,200,127);
    quadraticCurveTo(200,166,148,166);
    lineTo(115,166);
    lineTo(108,210);
    lineTo(69,210);
    lineTo(90,89);
    fillStyle = "#eee";
    fill();
    closePath();

    globalCompositeOperation = 'destination-out';

    // 'P' hole
    beginPath();
    moveTo(124,117);
    lineTo(146,117);
    quadraticCurveTo(160,117,160,127);
    quadraticCurveTo(160,145,146,145);
    lineTo(120,145);
    lineTo(124,117);
    fillStyle = '#000';
    fill();
    closePath();
}

with(context) {
    // Background
    fillStyle = '#000';
    fillRect(0,0,300,300);

    // Simply reference the canvas element when drawing
    drawImage(newCanvas, 0, 0);
}

答案 1 :(得分:0)

我知道这已经很老但是......你在第二次尝试时没有正确使用剪辑。剪辑后的所有内容都只会在剪裁区域绘制。

所以你可以:

  • 剪裁洞并重绘背景



var context = document.getElementById('test').getContext('2d');

// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);


// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();


// 'P' hole clip
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.clip();

// Redraw Background in the clipped area
context.fillStyle = '#000';
context.fillRect(0,0,300,300);

<canvas id="test" width="300" height="300">
&#13;
&#13;
&#13;

  • 夹住孔的外侧部分并绘制P

&#13;
&#13;
var context = document.getElementById('test').getContext('2d');

// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);

// inverse 'P' hole clip
context.beginPath();
context.rect(0, 0, 300, 300);
context.lineTo(124,117);
context.lineTo(120,145);
context.lineTo(146,145);
context.quadraticCurveTo(160,145,160,127);
context.quadraticCurveTo(160,117,146,117);
context.lineTo(124,117);
context.clip();

// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
&#13;
<canvas id="test" width="300" height="300">
&#13;
&#13;
&#13;

此外,您不需要在此使用closePath