How to punch holes through overlaying div by applying canvas as a mask with CSS

Viewed 139

I have drawn a canvas with the following content:

enter image description here

How do I correctly set the canvas as a clipping mask in CSS for an entire div?

This is my code:

var punchHole = function(x, y, r, ctx){
    ctx.save()
    ctx.arc(x, y, r, 0, Math.PI * 2, false)
    ctx.clip()
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
    ctx.restore();
}

function draw() {
    var ctx = document.getElementById('splash-canvas').getContext('2d');
    var circles = [{x: 50, y: 50, r: 50}, {x: 75, y: 75, r: 50}];
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    for (var i=0; i<circles.length; i++){
        punchHole(circles[i].x, circles[i].y, circles[i].r, ctx)
    }
}
window.onload = draw;
.aside, .content, canvas{
  left:0;
  top:0;
  position:absolute;
  height: 100vh;
  width: 100vw;
  display: block;
}
.content{
  z-index:2;
  font-weight:bold;
  color:red;
  background:yellow;
}
.aside{
  color:green;
  z-index:3;
  height: 100vh;
  width: 100vw;
  display: block;
  mask: url(#splash-canvas);
}
canvas{
  z-index:5;
}
.hidden{
  overflow:hidden;
  width:0;
}
<div class="hidden"><canvas id="splash-canvas"  width="150" height="150"></canvas></div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<div class="aside">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>

As can be seen the canvas is applied as a mask, but it also shown itself and hides the content in the layer it masks. Not sure what I am doing wrong. What I'd expect to happen is that the black region should be replaced with the content of the .aside layer (green text), and the content of the .content layer (red text) should be visible through the hole (this already happens). I've tried storing the canvas inside a hidden div (overflow:hidden), but no dice. I've also tried hiding the canvas behind everything else on the screen, but it still shows on top.

1 Answers

You don't really need all that amount of code or canvas. What you want can be achieved with a background coloration using gradients.

.content{
  font-weight:bold;
  font-size:30px;
  color:#0000;
  background:                                   /* position */
   radial-gradient(farthest-side,red 98%,#0000) 20px  20px,
   radial-gradient(farthest-side,red 98%,#0000) 160px 100px,
   green;
  background-size:200px 200px; /* size of the circles */
  background-repeat:no-repeat;
  -webkit-background-clip:text;
          background-clip:text;
}
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>

Related