You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在P5JS中实现绘制动画倒放,完成多幅预设艺术作品循环切换效果?

p5.js 多艺术作品循环切换+倒放擦除效果实现

核心思路

要实现绘制、停留、倒放擦除、循环切换的效果,核心是把每个作品的绘制过程拆解为独立的帧步骤,而非一次性渲染完成,倒放时只需要反向执行绘制逻辑/回退到上一帧状态即可。

实现代码

// 全局状态配置
const CANVAS_W = 800, CANVAS_H = 1200; // 海报尺寸可自定义
const STAY_FRAMES = 180; // 作品停留时长,60帧约等于1秒,180即停留3秒
const WORK_COUNT = 3; // 预设作品总数
let works = []; // 存储所有作品的绘制帧序列
let currentWork = 0;
let currentFrameIdx = 0;
let runState = "draw"; // 运行状态:draw正向绘制 / stay停留 / erase倒放擦除 / switch切换作品
let stayTimer = 0;

function preload() {
  // 预生成所有作品的绘制帧序列
  for (let i = 0; i < WORK_COUNT; i++) {
    works.push(createWorkFrames(i));
  }
}

function setup() {
  createCanvas(CANVAS_W, CANVAS_H);
  background(255);
  strokeWeight(2);
}

function draw() {
  switch(runState) {
    case "draw":
      // 执行当前帧的绘制操作
      works[currentWork][currentFrameIdx]();
      currentFrameIdx++;
      // 绘制完成切换到停留状态
      if (currentFrameIdx >= works[currentWork].length) {
        runState = "stay";
        stayTimer = 0;
      }
      break;
    case "stay":
      stayTimer++;
      if (stayTimer >= STAY_FRAMES) {
        runState = "erase";
      }
      break;
    case "erase":
      // 倒放:重绘到上一帧的状态
      background(255);
      currentFrameIdx--;
      for (let i = 0; i < currentFrameIdx; i++) {
        works[currentWork][i]();
      }
      // 擦除完成切换到作品切换状态
      if (currentFrameIdx <= 0) {
        runState = "switch";
      }
      break;
    case "switch":
      // 循环切换到下一个作品
      currentWork = (currentWork + 1) % WORK_COUNT;
      currentFrameIdx = 0;
      runState = "draw";
      break;
  }
}

/**
 * 生成单个作品的绘制帧序列
 * @param {number} workId 作品编号 0/1/2
 * @returns {Array<Function>} 每一步绘制操作的函数数组
 */
function createWorkFrames(workId) {
  const frames = [];
  switch(workId) {
    case 0:
      // 作品1示例:随机斜线
      for (let i = 0; i < 120; i++) {
        const x1 = random(CANVAS_W), y1 = random(CANVAS_H);
        const x2 = random(CANVAS_W), y2 = random(CANVAS_H);
        frames.push(() => {
          stroke(0);
          line(x1, y1, x2, y2);
        });
      }
      break;
    case 1:
      // 作品2示例:彩色圆形
      for (let i = 0; i < 90; i++) {
        const x = random(CANVAS_W), y = random(CANVAS_H);
        const r = random(20, 70);
        const fillColor = color(random(255), random(80, 180), random(200));
        frames.push(() => {
          noStroke();
          fill(fillColor);
          circle(x, y, r);
        });
      }
      break;
    case 2:
      // 作品3示例:网格色块
      for (let x = 0; x < CANVAS_W; x += 40) {
        for (let y = 0; y < CANVAS_H; y += 40) {
          const gray = random(50, 220);
          frames.push(() => {
            noStroke();
            fill(gray);
            rect(x, y, 38, 38);
          });
        }
      }
      break;
  }
  return frames;
}

优化提示

  • 如果作品绘制步骤较多,倒放时逐帧重绘性能不足,可以每间隔5-10帧用get()方法存储画布快照,倒放时直接调用image()渲染对应快照即可,运行效率会大幅提升
  • 可以在擦除完成后加几帧全白停留,避免作品切换时出现视觉跳变

内容的提问来源于stack exchange,提问作者Mr Loosid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 10:06:04