inputs e.g. slider not work well with p5

Here’s my take:

import P5 from "npm:p5";

function p5(sketch) {
  const node = document.body.appendChild(document.createElement("div"));
  const p = new P5(sketch, node);
  const draw = p.draw;
  p.draw = () => node.isConnected ? draw.apply(p, arguments) : p.remove();
  return node;
}

You can use like so:

const color = view(Inputs.color({label: "Color", value: "#dc3f74"}));
p5((p) => {
  p.setup = () => {
    p.createCanvas(width, 300);
    p.textAlign(p.CENTER);
    p.textFont("sans-serif");
    p.textStyle(p.BOLD);
  };
  const c = p.color(color);
  p.draw = () => {
    p.translate((p.millis() / 10) % p.width, p.height / 2);
    p.clear();
    p.fill(c).textSize(100);
    p.text("p5.js", 0, 0);
  };
})

The idea is that the draw method checks whether the sketch’s node is still connected, and if it’s not, it calls p.remove to terminate the animation loop. This way when you trigger the sketch to be re-created, as when the input value changes, you’re getting a new sketch and throwing away the old one.

Also note that you can write this in a way that doesn’t re-recreate the sketch when the input changes, and instead refers to the latest input value within the draw loop. That looks like this:

const colorInput = display(Inputs.color({label: "Color", value: "#dc3f74"}));
p5((p) => {
  p.setup = () => {
    p.createCanvas(width, 300);
    p.textAlign(p.CENTER);
    p.textFont("sans-serif");
    p.textStyle(p.BOLD);
  };
  p.draw = () => {
    const c = p.color(colorInput.value);
    p.translate((p.millis() / 10) % p.width, p.height / 2);
    p.clear();
    p.fill(c).textSize(100);
    p.text("p5.js", 0, 0);
  };
})

Use whichever technique you prefer!

I’ve also opened a small PR so that p5 is a built-in, so this “just works” without needing to import anything or writing a helper.

1 Like