Как пробить отверстия через наложение div, применив canvas в качестве маски с помощью CSS

#javascript #css #canvas

Вопрос:

Я нарисовал холст со следующим содержимым:

введите описание изображения здесь

Как мне правильно установить canvas в качестве обтравочной маски в CSS для всего div?

Это мой код:

 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> 

Как видно, canvas применяется в качестве маски, но он также показывает себя и скрывает содержимое в слое, который он маскирует. Не уверен, что я делаю не так. Чего я ожидаю, так это того, что черная область должна быть заменена содержимым .aside слоя (зеленый текст), а содержимое .content слоя (красный текст) должно быть видно через отверстие (это уже происходит). Я пробовал хранить холст внутри скрытого div (переполнение: скрыто), но без кубиков. Я также пытался скрыть холст за всем остальным на экране, но он все равно отображается сверху.

Комментарии:

1. Как можно видеть, холст применяется как маска -> он не применяется как маска. Где вы прочитали, что холст можно использовать в качестве маски? это невыполнимо

2. Я никогда раньше не работал с canvas, однако в моем примере есть 3 слоя: 1. красный текст, 2. зеленый текст, 3. холст (маска). В маске есть дырка. Я могу ясно видеть сквозь него слой 1, однако я не могу видеть промежуточный слой, поэтому я делаю вывод, что маска была применена к слою 2. В противном случае я должен увидеть зеленый текст, наложенный на красный. CSS mask использует альфа-информацию, чтобы решить, что видно, а что нет, и холст в этом случае явно имеет альфа-информацию.

3. удалите свойство mask, и вы увидите тот же результат (маска здесь ничего не делает). overflow:hidden ничего не делает, потому что canvas является position:absolute . Либо удалите position:absolute, либо добавьте position: относительно его родительского элемента

4. вы правы насчет скрытой проблемы переполнения. однако вот скриншот с отключенной и включенной маской: imgur.com/a/OZqh0J0 определенно что-то происходит, но не то, чего я ожидал.

5. Я проверил, и вы правы. Я думаю, что все ваши комментарии можно было бы скомпилировать в хороший ответ на вопрос. Если вы хотите это сделать, я отмечу это как решение. Знать, что решения нет, так же хорошо, как знать правильное существующее решение.

Ответ №1:

На самом деле вам не нужно столько кода или canvas. То, что вы хотите, может быть достигнуто с помощью окраски фона с использованием градиентов.

 .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> 

Комментарии:

1. извините, мой фрагмент был просто для того, чтобы доказать концепцию. чего я пытаюсь добиться, так это растворить верхний слой, чтобы можно было увидеть слой за ним. это то, что я пытаюсь воспроизвести: imgur.com/swm6ifG , поэтому в основном я хотел поработать с canvas, чтобы оживить маску. Я не могу принять этот ответ, поскольку он не отвечает на вопрос.