按下键盘时隐藏和显示背景图像,保留覆盖元素

Hide and show background image when keyboard pressed, preserving overlay elements

我想在单击鼠标时在图像上绘制椭圆,当我按下键盘时,交替隐藏和显示下面的图像,而不清除椭圆。

我正在使用 createGraphics() 来存储图像数据,并使用 remove() 所以当按下键盘时我发现图像消失了,但它不起作用

这是我尝试做的事情的草图:

let isMouseBeeingPressed = false;
let img;
let isShow = true
let bufferImg;

function preload() {
  img = loadImage(
    "https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
  );
}

function setup() {
  createCanvas(500, 500);
  background(255);
  loadImageBuffer();

}

function loadImageBuffer() {
  bufferImg = createGraphics(400, 400);
  bufferImg.image(img, 0, 0);
  image(bufferImg, 0, 0);

}


function draw() {
    if(isMouseBeeingPressed) {
      stroke(0, 0, 0, 50);
      fill(255);
      ellipse(mouseX, mouseY, 20);
    }
}

function keyPressed() {
  
  if(isShow) {
    bufferImg.remove();
  } else {
    image(bufferImg, 0, 0);
  }
  
   
  console.log('isShow:', isShow);
  return isShow = !isShow;
}

function mousePressed() {
  isMouseBeeingPressed = true;
}

function mouseReleased() {
  isMouseBeeingPressed = false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

知道如何实现吗?

最好的方法可能是将椭圆绘制到单独的缓冲区 (p5.Graphics),然后根据需要将其绘制在图像或空白背景之上。另一种方法是记录数组中每个椭圆的位置,以便可以重新绘制它们。然而,后一种方法将使用更多内存,并且在绘制许多椭圆后打开和关闭图像会有明显的延迟。

方法 #1(通过 p5.Graphics 渲染)

let img;
let graphics;
let isShow = true;

function preload() {
  img = loadImage(
    "https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
  );
}

function setup() {
  createCanvas(500, 500);
  background(255);
  image(img, 0, 0);
  graphics = createGraphics(width, height);
}

function draw() {
  if (mouseIsPressed) {
    graphics.stroke(0, 0, 0, 50);
    graphics.fill(255);
    graphics.ellipse(mouseX, mouseY, 20);
    
    background(255);
    if (isShow) {
      image(img, 0, 0);
    }
    image(graphics, 0, 0);
  }
}

function keyPressed(e) {
  isShow = !isShow;
  background(255);
  if (isShow) {
    image(img, 0, 0);
  }
  
  image(graphics, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

更新: 关于此方法需要注意的一件事是,每当按下鼠标时,都必须重新绘制整个场景(白色背景、图像(如果适用)和前景)。这样做的原因是抗锯齿和透明度。当您在 graphics 缓冲区上绘制椭圆时,由于抗锯齿,边缘将具有一些部分透明的像素。如果您重复绘制缓冲区作为覆盖层而不重新绘制其后面的内容,那么部分透明的像素将变得越来越不透明,直到它们变成黑色。这将导致您的椭圆的外边缘稍粗且像素化程度更高。

方法 #2(椭圆位置数组)

let img;
let isShow = true
let positions = [];

function preload() {
  img = loadImage(
    "https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
  );
}

function setup() {
  createCanvas(500, 500);
  background(255);
  image(img, 0, 0);
}


function draw() {
  if (mouseIsPressed) {
    stroke(0, 0, 0, 50);
    fill(255);
    ellipse(mouseX, mouseY, 20);
    positions.push([mouseX, mouseY]);
  }
}

function keyPressed() {
  isShow = !isShow;
  background(255);
  if (isShow) {
    image(img, 0, 0);
  }
  stroke(0, 0, 0, 50);
  fill(255);
  for (const [x, y] of positions) {
    ellipse(x, y, 20);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>