在 p5.js 中主动绘制 "under" 个半透明区域

Actively drawing "under" a translucent area in p5.js

我 运行 在开发更大的 p5.js 草图时遇到了一个令人费解的问题,我的解决方案并不适合我。所以,我把它归结为这个(诚然是蹩脚的)草图。

此 p5.js 草图每帧绘制几个 运行domly 大小和颜色的点。在 canvas 的中心是一个 t运行 半透明的蓝色填充矩形,看起来位于观察者和点之间。问题出在 t运行slucent 蓝色区域。草图有效,但我忍不住认为有更好的方法来实现 t运行slucency.

var cells;
var cellsz = 10;
var wid, hgt;

function setup()
{
  wid = floor(windowWidth / cellsz);
  hgt = floor(windowHeight / cellsz);
  createCanvas(windowWidth, windowHeight);
  frameRate(15);

  cells = new Array(wid);

  for (x = 0; x < wid; x++) {
    cells[x] = new Array(hgt);
    for (y = 0; y < hgt; y++) {
      cells[x][y] = false;
    }
  }
}

function cell_draw(c)
{
  strokeWeight(1);
  stroke(c.r, c.g, c.b);
  fill(c.r, c.g, c.b);
  ellipse(c.x, c.y, c.w, c.w);
}

function cell_new()
{
  var x = int(floor(random(wid)));
  var y = int(floor(random(hgt)));

  var c = {
    x: x * cellsz,
    y: y * cellsz,
    w: random(cellsz * 2),
    r: floor(random(256)),
    g: floor(random(256)),
    b: floor(random(256))
  };

  cells[x][y] = c;
  cell_draw(c);
}

// draw a translucent blue filled rectangle in the center of the window
function overlay()
{
  strokeWeight(1);
  stroke(0, 0, 255, 75);
  fill(0, 0, 255, 75);
  var w = windowWidth / 4;
  var h = windowHeight / 4;
  rect(w, h, w * 2, h * 2);
}

// erase what's in the center of the window, then redraw the underlying cells
function underlay()
{
  strokeWeight(1);
  stroke(255);
  fill(255);
  var w = windowWidth / 4;
  var h = windowHeight / 4;
  rect(w, h, w * 2, h * 2);

  var x0 = floor((w / cellsz) - 2);
  var y0 = floor((h / cellsz) - 2);
  var x1 = floor(x0 + 3 + ((w * 2) / cellsz));
  var y1 = ceil(y0 + 3 + ((h * 2) / cellsz));

  for (x = x0; x <= x1; x++) {
    for (y = y0; y <= y1; y++) {
      if (cells[x][y]) {
        cell_draw(cells[x][y]);
      }
    }
  }
}

function draw()
{
  underlay();

  for (i = 0; i < 5; i++) {
    cell_new();
  }

  overlay();
}
body {padding: 0; margin: 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.js"></script>

代码背后的基本思想是 canvas 被量化为固定大小 cells。每个单元格包含零个或一个点对象(它的位置、直径和颜色)。当每个新的 运行dom 点被选中时,它被保存到适当的单元格中。这用作 canvas 中内容的逻辑内存。 (虽然它并不完美,因为它不处理绘制点的顺序。但是,无论如何,我们都是这里的朋友。)

我一直在为 t运行slucent 区域的基本问题而苦苦挣扎。最初,我每次都重新绘制整个框架,似乎是处理方式......但是对象太多了。绘制每一帧花费的时间太长了。最后,我吹掉了 t运行slucent 矩形下方的区域,只重新绘制了受影响的对象,然后在顶部放置了一个新的 t运行slucent 矩形。

有没有我可以在这里应用的技术,性能更好,或者使用更少的代码,或者...(喘气)两者都有?

您的方法非常合理,但您可以通过使用缓冲图像而不是二维数组来存储底层来简化它。在上面画点,然后每一帧将整个缓冲区绘制到屏幕上,然后在其上绘制矩形覆盖。这样做的好处是不局限于数组位置,将来也可以解决类似的分层问题。

查看我的回答 了解更多信息,但方法是这样的:

var buffer;

function setup() {
  createCanvas(windowWidth, windowHeight);
  frameRate(15);

  buffer = createGraphics(width, height);
  
  //start with white background
  buffer.background(255);
}

function drawRandomCircleToBuffer() {
  buffer.noStroke();
  buffer.fill(random(255), random(255), random(255));
  var diameter = random(5, 20);
  buffer.ellipse(random(buffer.width), random(buffer.height), diameter, diameter);
}

function overlay() {
  strokeWeight(1);
  stroke(0, 0, 255, 75);
  fill(0, 0, 255, 75);
  rect(mouseX, mouseY, 200, 200);
}

function draw() {
  
  drawRandomCircleToBuffer();

  image(buffer, 0, 0);
  overlay();
}
body {padding: 0; margin: 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.0/p5.js"></script>