Hi @Marc,
this looked really promising!
Can’t seem to get it working in Jupyterlab, I tried all morning!
Decided to create a script file and load it. Could not get the script loaded,
so I read in the file and passed the contents as part of the html.
The globals also give me a headache: I tried passing them in as parameters,
only to get errors…
Is there an easy way to share a notebook, other than copy and paste here?
This is what I have now:
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",
#"jquery": "https://code.jquery.com/jquery-3.4.1.min.js"
}
pn.extension(
js_files=js_urls
)
js_module_urls_str = "".join([f"<script type='module' src='{value}'></script>" for value in js_urls.values()])
extension_pane = pn.pane.HTML(js_module_urls_str,\
#+css_urls_str,
width=0, height=0, sizing_mode="fixed", margin=0)
extension_pane
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,
}
div_name = "p5_ts_sketch"
p5_html = f"""
<!-- **************************************************** this does not really work....
<script>
const inlineScript = document.createElement('script')
script.type='text/javascript';
script.src = 'p5_ts_sketch.js'
//script.innerHTML = 'alert("Inline script loaded!")'
document.head.append(script)
</script>
************************************************************************ -->
<div id="{div_name}" style="float:left;padding-left:5mm;border:2px solid black; height:10cm;width:100%;">
<h1>Step Approximation</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)
with open('p5_ts_sketch.js') as f:
p5_ts_sketch_script = f.read()
code = f"""
{p5_ts_sketch_script}
console.log("target")
const target = document.getElementById("{div_name}");
console.log(target);
let myp5_sketch = new p5( p5_ts_sketch, "{div_name}", number_of_terms_slider );
console.log( "created "+ myp5_sketch)
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);
"""
p5_sketch = pn.pane.HTML(p5_html, width=650, height=550)
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()
with the java script file p5_ts_sketch.js
const p5_ts_sketch = (p55, number_of_terms, mouse_x, mouse_y, mouse_clicks ) => {
// Fourier Series
// Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/125-fourier-series.html
// https://youtu.be/Mm2eYfj0SgA
// https://editor.p5js.org/codingtrain/sketches/SJ02W1OgV
// minor mods to work with pyviz: https://discourse.holoviz.org/t/p5-js-example/1551/5
let n_terms = number_of_terms; // can't get these to work in any variation....
let mouse_x_ = mouse_x;
let mouse_y_ = mouse_y;
let mouse_clicks_ = mouse_clicks;
let time = 0;
let wave = [];
let x_vals = [];
let looping = true;
p55.setup = () => {
let canvas = p55.createCanvas(600, 400);
looping = true;
console.log("Created Canvas" + canvas)
};
p55.draw = () => {
p55.background(0);
p55.translate(150, 200);
//mouse_x_.value = p55.mouseX;
//mouse_y_.value = p55.mouseY;
let x = 0;
let y = 0;
let n = 5; //number_of_terms_.value;
// draw the vectors and circles
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);
p55.stroke(255);
p55.line(prevx, prevy, x, y);
}
x_vals.unshift(x);
wave.unshift(y);
// draw the path being traced out
p55.beginShape();
p55.noFill();
for (let i = 0; i < wave.length; i++) {
p55.vertex(x_vals[i], wave[i] );
}
p55.endShape();
// draw the generated function
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();
if (wave.length > 250) {
wave.pop();
x_vals.pop()
}
time += 0.05;
};
// --------------------------------------------------------------------------------------------
p55.checkLoop = () => {
if (this.checked()) {
p55.loop();
} else {
p55.noLoop();
}
};
// --------------------------------------------------------------------------------------------
p55.mousePressed = () => {
p55.noLoop();
};
// --------------------------------------------------------------------------------------------
p55.mouseReleased = () => {
p55.loop();
};
// --------------------------------------------------------------------------------------------
p55.mouseClicked = () => {
//mouse_clicks_.value += 1;
if (looping ) {
p55.noLoop();
looping = false;
} else {
p55.loop();
looping = true;
}
};
// --------------------------------------------------------------------------------------------
p55.keyPressed = () => {
console.log( mouse_x_.value );
mouse_x_.value += 1;
};
// --------------------------------------------------------------------------------------------
};
Just to be sure, I chose to test it with a stand alone html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>P5 Time Series</title>
</head>
<body>
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
<script language="javascript" type="text/javascript" src="./p5_ts_sketch.js"></script>
<div id="p5_ts_sketch_1"></div>
<script>
let number_of_terms_slider = {}; number_of_terms_slider.value = 5;
let mouse_x = {}; mouse_x .value = 5;
let mouse_y = {}; mouse_y .value = 5;
let mouse_clicks = {}; mouse_clicks .value = 5;
let myp5_sketch = new p5( p5_ts_sketch, "p5_ts_sketch_1", number_of_terms_slider, mouse_x, mouse_y, mouse_clicks );
</script>
</body>
</html>