Canvas 'Clip' обратного действия? - PullRequest
6 голосов
/ 27 января 2011

Предполагая, что у меня есть:

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

Спасибо за вашу помощь!

Ответы [ 2 ]

7 голосов
/ 25 апреля 2011

Я понимаю, что вы спрашивали об этом некоторое время назад, но у меня есть для вас ответ.

Ваш первый пример был наполовину правильным.Использование target-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);
}
0 голосов
/ 15 марта 2017

Я знаю, что это очень старая версия, но ... вы неправильно используете клип во второй попытке. Все, что идет после клипа, будет нарисовано только в обрезанной области.

так что вы можете либо:

  • Обрежьте отверстие и перерисуйте фон

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 здесь.

...