P5.js example

Hi @ea42gh

I played a bit around with inspired by How to get a JavaScript event to trigger a Python event.

You can now

  • Change the number of terms with the slider
  • Get the mouse position back and information on mouse clicks.
  • Stop the loop when mouse down on the canvas.

I could not get the loop stopped via the panel checkbox. I’m sure there is a way. @xavArtley. Do you know how to catch an event from the checkbox on the js side? Thanks in advance.

from panel.util import value_as_date
import param
import panel as pn
pn.extension()
from awesome_panel_extensions.web_component import WebComponent
js_urls = {
    "p5": "https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"
}
pn.extension(
    js_files=js_urls
)

number_of_terms_slider = pn.widgets.IntSlider(value=5, start=1, end=20,step=1)
start_stop_checkbox = pn.widgets.Checkbox(name="Enabled", value=True)
mouse_x_input=pn.widgets.FloatInput(name="Mouse X")
mouse_y_input=pn.widgets.FloatInput(name="Mouse Y")
mouse_clicks_input = pn.widgets.IntInput(name="Clicks")
args = {
    "number_of_terms": number_of_terms_slider,
    "start_stop": start_stop_checkbox,
    "mouse_x": mouse_x_input,
    "mouse_y": mouse_y_input,
    "mouse_clicks": mouse_clicks_input,
}

p5_html = """
<div id="sketch2" style="float:left;height:10cm;width:10cm;padding-left:5mm;">
    <h1>Sketch2</h1>
</div>"""
# comm to run the js script
comm_py_to_js = pn.widgets.StaticText(style={'visibility': 'hidden', 'width': 0, 'height': 0, 'overflow': 'hidden'}, margin=0)
# comm to return informations from javascript to python
comm_js_to_py = pn.widgets.StaticText(style={'visibility': 'hidden', 'width': 0, 'height': 0, 'overflow': 'hidden'}, margin=0)

code = """
console.log("args");
console.log(start_stop);
console.log(start_stop.value);
console.log(number_of_terms);
console.log(mouse_x);
console.log(mouse_y);
console.log(mouse_clicks);

console.log("target")
const target = document.getElementById("sketch2");
console.log(target);


const sketch2 = (p55) => {
// Fourier Series
// Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/125-fourier-series.html
// https://youtu.be/Mm2eYfj0SgA
// https://editor.p5js.org/codingtrain/sketches/SJ02W1OgV

let time = 0;
let wave = [];

let n = number_of_terms.value;

p55.setup = () => {
    p55.createCanvas(600, 400);
    console.log("Created Canvas")
};

p55.mousePressed = () => {
  console.log("pressed");
  p55.noLoop();
};

p55.mouseReleased = () => {
  p55.loop();
};

p55.mouseClicked = () => {
    mouse_clicks.value += 1;
}

p55.draw = () => {
  p55.background(0);
  p55.translate(150, 200);
  mouse_x.value = p55.mouseX;
  mouse_y.value = p55.mouseY;

  console.log("DRAW")
  let x = 0;
  let y = 0;
  n = number_of_terms.value;

  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);

    p55.stroke(255, 100);
    p55.noFill();
    p55.ellipse(prevx, prevy, radius * 2, radius * 2);

    //fill(255);
    p55.stroke(255);
    p55.line(prevx, prevy, x, y);
    //ellipse(x, y, 8);
  }

  wave.unshift(y);

  p55.translate(200, 0);
  p55.line(x - 200, y, 0, wave[0]);
  p55.beginShape();
  p55.noFill();
  for (let i = 0; i < wave.length; i++) {
    p55.vertex(i, wave[i] );
  }
  p55.endShape();

  time += 0.05;

  if (wave.length > 250) {
    wave.pop();
  }
};
};
let myp5_sketch2 = new p5(sketch2, "sketch2");
"""

p5_sketch = pn.pane.HTML(p5_html, width=350, height=350)
comm_py_to_js.jscallback(args=args, value=code)
def _execute_js_code(*_):
    comm_py_to_js.param.trigger("value")
pn.state.onload(_execute_js_code)
pn.Column(
    start_stop_checkbox,
    number_of_terms_slider,
    mouse_x_input,
    mouse_y_input,
    mouse_clicks_input,
    p5_sketch,
    comm_py_to_js,
    sizing_mode="stretch_height",
).servable()