如何在 P5JS 中反转绘图的动画(post 中有更多详细信息)

How do I reverse the animation of a drawing in P5JS (more details in post)

源代码:https://editor.p5js.org/theruantan/sketches/aFXKo_s86

基本上我正在尝试做一个我预先设计好的pseudo generative poster that swaps between 3 artworks。我们的想法是加载一件艺术品,等待几秒钟然后反转(基本上将其擦除)绘图为空白 canvas 然后加载下一件并无限重复。

我只是想重现我在这里看到的反转动画:https://www.reddit.com/r/generative/comments/q6krwj/lines_p5js/

没有像这样自动倒回动画的方法。您可以做一些非常占用内存的事情,例如将动画的每一帧都保存为图像,然后向后播放整个动画,但这会占用大量内存。相反,您可以反转为各种形状设置动画的逻辑:

let masks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Create Masks for Artwork Background
let switches = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // To switch on each background line

let mainMask = 400; // Create Main mask to reveal artwork

let cityActiveState = 0; // To determine if the current artwork is active or erased -- either 0 or 1.

let sunXPos = 0; // To Move the sun around
let sunYPos = -100;

let rods = -100; // Animate lightning rods for city

function setup() {
  createCanvas(180, 216);
  frameRate(60);

  console.log(`${switches.length} Swithces`);
  console.log(`${masks.length} Masks`);
}

function draw() {
  let beige = color(251, 242, 224);
  let red = color(245, 105, 96);
  let blue = color(96, 152, 190);
  let green = color(124, 167, 122);
  let headBlack = color(60, 60, 59);
  let textBlack = color(112, 111, 111);

  background(beige);

  push();
  scale(0.2);
  translate(50, 240);
  citySkyline(red, beige);
  pop();
}

function citySkyline(color1, color2) {
  // Animate artwork
  if (cityActiveState == 0) {
    sunXPos = 650;
    if (!switches[0]) {
      switches[0] = 1;
    }
    let animating = false;
    for (let i = 0; i < switches.length; i++) {
      if (switches[i] == 1) {
        if (masks[i] < 800) {
          masks[i] += 20;
          animating = true;
        }
        if (masks[i] >= 300) {
          if (i + 1 < switches.length) {
            switches[i + 1] = 1;
          }

          if (i == 12) {
            // Only increase these once masks[12] reaches 300
            if (mainMask < 1500) {
              mainMask += 10;
              animating = true;
            }

            if (rods < 371) {
              rods += 15;
              animating = true;
            }

            if (sunYPos < 140) {
              sunYPos += 7.5;
              animating = true;
            }
          }
        }
      }
    }
    if (!animating) {
      console.log("city is now active");
      cityActiveState = 1;
    }
  } else if (cityActiveState == 1) {
    // Reverse animation
    let animating = false;
    if (mainMask > 400 || rods > -100 || sunYPos > -100) {
      animating = true;
      if (mainMask > 400) {
        mainMask -= 10;
      }

      if (rods > -100) {
        rods -= 15;
      }

      if (sunYPos > -100) {
        sunYPos -= 7.5;
      }
    } else {
      if (switches[switches.length - 1]) {
        switches[switches.length - 1] = 0;
      }
      for (let i = switches.length - 1; i >= 0; i--) {
        if (switches[i] == 0) {
          if (masks[i] > 0) {
            masks[i] -= 20;
            animating = true;
          }
          if (masks[i] <= 300) {
            // Begin reversing the next bar
            switches[i - 1] = 0;
          }
        }
      }
    }
    if (!animating) {
      console.log("city is now inactive");
      cityActiveState = 0;
    }
  }

  // draw actual artwork
  push();
  noStroke();
  fill(color1);
  translate(225, 285);
  rect(50, 0, 250, 20);
  rect(0, 55, 350, 10);
  rect(0, 95, 350, 10);
  rect(0, 135, 350, 50);
  rect(0, 215, 350, 30);
  rect(0, 275, 350, 10);
  rect(0, 315, 350, 40);
  rect(0, 385, 350, 60);
  rect(0, 475, 350, 40);
  pop();

  // reveal artwork
  push();
  noStroke();
  fill(color2);
  rectMode(RADIUS);
  rect(mainMask, 400, 400, 400);
  pop();

  push();
  noStroke();
  fill(color1);
  rect(0, 0, masks[0], 100);
  rect(0, 110, masks[1], 70);
  rect(0, 190, masks[2], 50);
  rect(0, 250, masks[3], 35);
  rect(0, 315, masks[4], 25);
  rect(0, 370, masks[5], 10);
  rect(0, 410, masks[6], 10);
  rect(0, 490, masks[7], 10);
  rect(0, 550, masks[8], 10);
  rect(0, 590, masks[9], 10);
  rect(0, 660, masks[10], 10);
  rect(0, 750, masks[11], 10);
  pop();

  // draw lighting rods
  push();
  noStroke();
  fill(color2);
  translate(0, 100);
  rect(rods + 30, 0, 20, 140);
  translate(0, 40);
  rect(rods, 0, 10, 100);
  pop();

  // draw sun
  push();
  noStroke();
  fill(color2);
  circle(sunXPos, sunYPos, 143);
  pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

我精简了代码,不得不 fiddle 解决了一些错误才能完成这项工作。希望基本概念清楚。