Including a js file with Streamlit

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 :slightly_frowning_face:

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