skip to Main Content

I have script that writes two triangle, blue and red.
I want to make transparent this area instead of blue and red like Paper-cutting work.
(I want to put the image background, so it must be transparent not white.)

I am struggling with the method clip() but it doesn’t work what I want.
How can I make it?

function draw() {
  var canvas = document.getElementById('test');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');
    ctx.fillStyle = 'green';
    ctx.fillRect(0, 0, 400, 400);
    ctx.fillStyle = 'blue';
    ctx.beginPath();
    ctx.moveTo(50, 70);
    ctx.lineTo(100, 100);
    ctx.lineTo(150, 200);
    ctx.closePath();
    ctx.fill();


    ctx.fillStyle = 'red';
    ctx.beginPath();
    ctx.moveTo(100, 170);
    ctx.lineTo(300, 200);
    ctx.lineTo(350, 300);
    ctx.closePath();
    ctx.fill();

  }
}
<body onload="draw();">
  <canvas id="test" width="400px" height="300px"></canvas>
</body>

2

Answers


  1. Something like this? Draw the overlay, cut it out, then draw the background.

    function draw() {
      let img = document.createElement("img");
      // Some random test image
      img.src = "https://wallup.net/wp-content/uploads/2017/03/27/21837-test_patterns.jpg";
      img.onload = () => {
        var canvas = document.getElementById('test');
        if (canvas.getContext) {
          var ctx = canvas.getContext('2d');
    
          // The top layer
          ctx.fillStyle = 'green';
          ctx.fillRect(0, 0, 400, 400);
    
          // Cutout top layer
          ctx.beginPath();
          ctx.moveTo(50, 70);
          ctx.lineTo(100, 100);
          ctx.lineTo(150, 200);
    
          ctx.moveTo(100, 170);
          ctx.lineTo(300, 200);
          ctx.lineTo(350, 300);
          ctx.closePath();
          ctx.clip();
    
          // Background
          ctx.drawImage(img, 0, 0);
        }
      }
    }
    <body onload="draw();">
      <canvas id="test" width="400px" height="300px"></canvas>
    </body>
    Login or Signup to reply.
  2. You can use ctx.globalCompositeOperation = 'xor' if the image is not part of the canvas and you need actual transparency on the canvas. See mdn:

    "xor": Shapes are made transparent where both overlap and drawn normal everywhere else.

    Else, clip() works fine. Yours is not working might because you drawed two shape and clip() actually takes the intersection, not union of the two, and the two shape has nearly zero intersected region.

    function draw() {
      var canvas = document.getElementById('test');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        
        ctx.fillStyle = 'green';
        ctx.fillRect(0, 0, 400, 400);
        
        ctx.globalCompositeOperation = 'xor';
        ctx.beginPath();
        ctx.moveTo(50, 70);
        ctx.lineTo(100, 100);
        ctx.lineTo(150, 200);
        ctx.closePath();
        ctx.moveTo(100, 170);
        ctx.lineTo(300, 200);
        ctx.lineTo(350, 300);
        ctx.closePath();
        ctx.fill();
    
        ctx.globalCompositeOperation = 'source-over'; // reset to default or whatever you were using
      }
    }
    canvas {
      background-image: url('https://i.sstatic.net/XZ4V5.jpg');
      background-size: cover;
    }
    <body onload="draw();">
      <canvas id="test" width="400" height="300"></canvas>
    </body>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search