import panel as pn
import param
from panel.custom import JSComponent
class P5Sketch(JSComponent):
num_components = param.Integer(default=5, bounds=(1, 15))
_esm = """
import p5 from "https://esm.sh/p5"
export function render({model, el}) {
function sketch(p) {
let time = 0;
let wave = [];
let run = true;
p.setup = () => {
const canvas = p.createCanvas(model.width, model.height)
canvas.canvas.style.visibility = 'visible'
canvas.mousePressed(() => {
if (p.mouseX >= 0 && p.mouseX <= p.width && p.mouseY >= 0 && p.mouseY <= p.height) {
run = !run;
if (run) { p.loop(); } else { p.noLoop(); }
}
}
)};
p.draw = () => {
p.background(0);
p.translate(150, 200);
let x = 0;
let y = 0;
const n = model.num_components;
for (let i = 0; i < n; i++) {
let prevx = x;
let prevy = y;
let n = i * 2 + 1;
let radius = 75 * (4 / (n * Math.PI));
x += radius * Math.cos(n * time);
y += radius * Math.sin(n * time);
p.stroke(255, 100);
p.noFill();
p.ellipse(prevx, prevy, radius * 2, radius * 2);
p.stroke(255);
p.line(prevx, prevy, x, y);
}
wave.unshift(y);
p.translate(200, 0);
p.line(x - 200, y, 0, wave[0]);
p.beginShape();
p.noFill();
for (let i = 0; i < wave.length; i++) {
p.vertex(i, wave[i] );
}
p.endShape();
time += 0.05;
if (wave.length > 250) { wave.pop(); }
}
}
new p5(sketch, el)
}
"""
sketch = P5Sketch(height=400, width=600)
main=pn.Column(sketch.controls(["num_components"]), sketch, "**Mouse Press** starts/stops the animation")
pn.template.FastListTemplate(
site="Awesome Panel",
title="P5.js Fourier Demo",
main=[main],
main_layout=None,
theme_toggle=False,
theme="dark",
header_background="#111111",
main_max_width="650px",
).servable()