6

假设我有:

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”,但是用“孔”夹住部分,这样任何背景都会显示出来。

这是据我所知,但不完全是:

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();

谢谢您的帮助!

4

2 回答 2

7

我知道您前一阵子问过这个问题,但我有一个答案。

你的第一个例子是对的。使用destination-out 会起作用,但是为了不打扰您要绘制的画布,我们创建一个新的画布并在其中绘制它。

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

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);
}
于 2011-04-25T08:32:38.617 回答
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">

  • 夹住孔的外部并画出 P

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();
<canvas id="test" width="300" height="300">

此外,您不需要在closePath这里使用。

于 2017-03-14T22:23:11.827 回答