-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
p5 #1093
base: main
Are you sure you want to change the base?
p5 #1093
Conversation
Nice that you overload the draw function and thus don't need setInterval as we had previously. Beyond the (efficient) plumbing, I feel that we should give a nicer example—something that makes people want to use P5. Here's a possibility (although maybe a bit too much code? The example below is slightly adapted from R. Luke DuBois’s origin [Spirograph P5 example](https://p5js.org/examples/simulate-spirograph.html). (Click to switch modes.)
```js
const NUMSINES = view(Inputs.range([2, 50], {step: 1, value: 20, label: "number of wheels"}));
```
```js echo
display(
p5((p) => {
let sines = new Array(NUMSINES); // an array to hold all the current angles
let rad; // an initial radius value for the central sine
let i; // a counter variable
// play with these to get a sense of what's going on:
let fund = 0.005; // the speed of the central sine
let ratio = 1; // what multiplier for speed is each additional sine?
let alpha = 50; // how opaque is the tracing system
let trace = true; // are we tracing?
p.setup = () => {
p.createCanvas(710, 400);
rad = p.height / 4; // compute radius for central circle
p.background(dark ? 51 : 204); // clear the screen
for (let i = 0; i < sines.length; i++) {
sines[i] = p.PI; // start EVERYBODY facing NORTH
}
};
p.draw = () => {
if (!trace) {
p.background(dark ? 51 : 204); // clear screen if showing geometry
p.stroke(dark ? 255 : 0, 255); // pen color
p.noFill(); // don't fill
}
// MAIN ACTION
p.push(); // start a transformation matrix
p.translate(p.width / 2, p.height / 2); // move to middle of screen
for (let i = 0; i < sines.length; i++) {
let erad = 0; // radius for small "point" within circle... this is the 'pen' when tracing
// setup for tracing
if (trace) {
p.stroke(dark ? 255 : 0, dark ? 255 : 0, 255 * (p.float(i) / sines.length), alpha);
p.fill(dark ? 255 : 0, dark ? 255 : 0, 255, alpha / 2);
erad = 5.0 * (1.0 - p.float(i) / sines.length); // pen width will be related to which sine
}
let radius = rad / (i + 1); // radius for circle itself
p.rotate(sines[i]); // rotate circle
if (!trace) p.ellipse(0, 0, radius * 2, radius * 2); // if we're simulating, draw the sine
p.push(); // go up one level
p.translate(0, radius); // move to sine edge
if (!trace) p.ellipse(0, 0, 5, 5); // draw a little circle
if (trace) p.ellipse(0, 0, erad, erad); // draw with erad if tracing
p.pop(); // go down one level
p.translate(0, radius); // move into position for next sine
sines[i] = (sines[i] + (fund + fund * i * ratio)) % p.TWO_PI; // update angle based on fundamental
}
p.pop(); // pop down final transformation
};
p.mouseClicked = () => {
trace = !trace;
p.background(dark ? 0 : 255);
};
})
);
```
|
Sure, I can tinker on some better examples. Does the implementation look okay though otherwise? And are you supportive of adding |
Yeah I'm fine with it, especially because it solves the "plumbing" issue. But I can't think of a real use case. It's nice as a stand-alone app but it has its specific syntax, which is probably a bit obsolete now; and with p5-in-a-function needs you to prefix all the keywords (like |
@mbostock I've gone down a similar path as you have and implemented my own (opinionated) version (code here) Just dropping in a few notes on what I've done in case it's helpful:
draw(400, 400, (p5) => {
p5.rect(...)
}) Overall I felt like I needed a bit of tweaking for it to be more user friendly. Was planning on making a PR into Observable with the basics, but saw you already had one up. Cheers ! |
Adds p5.js to the set of built-in libraries (so it just works).