For the ones interested in this issue, here is a lot easier and intuitive solution (compared to my previous cumbersome one, where all the code was embedded in a single HTML page [DELETED]).
Limitations:
- At the moment
p5.min.js
is served only from CDN. In a future release of Streamlit it should be possible to serve it locally. - Multiple sketches are completely independent, and
p5.min.js
must be loaded for each of them (I didn’t give a better look into this, it’s probably possible to load it only once). - The sketch doesn’t return values to Streamlit because it i embedded into the HTML page
Anyway, it works for me.
I am using it to visualize data with more than 40 dedicated plots per page.
import streamlit as st
import streamlit.components.v1 as components, html
def p5js_sketch(sketch_file, js_params=None, height=200, width=200):
sketch = '<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.min.js"></script>'
sketch += '<script>'
if js_params:
sketch += js_params + "\n"
sketch += open(sketch_file, 'r', encoding='utf-8').read()
sketch += '</script>'
components.html(sketch, height=height, width=width)
cols = st.columns(2)
with cols[0]:
st.header("sketch 0")
p5js_sketch(
sketch_file="sketch.js",
js_params="const WIDTH=150; "
"const HEIGHT=150; "
"let BACKGROUND_COLOR='red'; "
"let CIRCLE_SIZE=30;",
)
with cols[1]:
st.header("sketch 1")
p5js_sketch(
sketch_file="sketch.js",
js_params="WIDTH=150; " # JS is tolerant and "let" / "const" can be avoided
"HEIGHT=150; "
"BACKGROUND_COLOR='orangered'; "
"CIRCLE_SIZE=60;",
)
js_params
are inserted without any check at he beginning of the sketch as global variables, to define the missing variables (here UPPERCASE):
sketch.js
// PARAMS are embedded here
function setup() {
createCanvas(WIDTH, HEIGHT);
}
function draw() {
background(BACKGROUND_COLOR);
circle(mouseX, mouseY, CIRCLE_SIZE);