Konva.JS how to subtract one layer from another?

63 Views Asked by At

I need the "drawingLayer" layer to serve as a mask for the "normalLayer" layer I've already tried a lot of things, but I can't subtract the "drawingLayer" from the "normalLayer" layer.

Perhaps I approached the task incorrectly, but the point is that I want to achieve a result so that I can erase or reveal the “normalLayer” layer with the left/right mouse button

here is codepen for clarity

function initializeKonva() {
  let container = document.querySelector('#MagicContainerCanvas');
  if (!container) {
    console.error('Container #MagicContainerCanvas not found');
    return;
  }

  let containerWidth = container.offsetWidth;
  let containerHeight = container.offsetHeight;

  let stage = new Konva.Stage({
    container: container,
    width: containerWidth,
    height: containerHeight
  });

  // Create a layer with a red filter
  let redFilterLayer = new Konva.Layer();
  stage.add(redFilterLayer);

  // Create a normal layer
  let normalLayer = new Konva.Layer();
  stage.add(normalLayer);

  // Loading Images into Layers
  loadImage(getLightSkin, redFilterLayer, true);
  loadImage(getLightMask, normalLayer, false);

  // Create a drawing layer
  let drawingLayer = new Konva.Layer();
  stage.add(drawingLayer);

  // Create a layer to display the brush
  let brushLayer = new Konva.Layer();
  stage.add(brushLayer);

  let isDrawing = false;
  let brushSize = 20;
  let currentLine;

  // Brush
  let brush = new Konva.Circle({
    x: -50,
    y: -50,
    radius: brushSize / 2,
    stroke: 'black',
    strokeWidth: 1,
    fill: 'rgba(0,0,0,0.2)'
  });
  brushLayer.add(brush);

  stage.on('mousedown', function(e) {
    isDrawing = true;
    let pos = stage.getPointerPosition();

    currentLine = new Konva.Line({
      stroke: 'black',
      strokeWidth: brushSize,
      globalCompositeOperation: e.evt.button === 2 ? 'destination-out' : 'source-over',
      points: [pos.x, pos.y],
      tension: 0.5,
      lineCap: 'round',
      lineJoin: 'round'
    });

    drawingLayer.add(currentLine);
  });

  stage.on('mousemove', function(e) {
    let pos = stage.getPointerPosition();
    brush.position({ x: pos.x, y: pos.y });
    brushLayer.batchDraw();

    if (isDrawing && currentLine) {
      let newPoints = currentLine.points().concat([pos.x, pos.y]);
      currentLine.points(newPoints);
      drawingLayer.batchDraw();
    }
  });

  stage.on('mouseup', function() {
    isDrawing = false;
  });

  stage.on('contextmenu', function(e) {
    e.evt.preventDefault();
  });
}
1

There are 1 best solutions below

0
lavrton On

I suggest not creating too many layers. Instead, create one layer and use Konva.Group to organize your scene.

As described in https://konvajs.org/docs/sandbox/Free_Drawing.html, you can use globalCompositeOperation property to subtract one group from another groups.

globalCompositeOperation: 'destination-out'