Switch Between Multiple p5.js Sketches in Single Webpage

TLDR: Is it better to have lots of instances of p5.js or keep switching the code in the global mode? Is there a way to treat a JS file as a single instance of p5.js without modifying the code inside the file?

I have several JS files, each as a self-contained p5.js sketch in global mode. My goal is to have a webpage with a parent object for each, say, a div. I would only like one sketch to run at a time, however.

There are two methods I can see that seem optimal for this situation. 1. Use global mode and dynamically change which code is being run and which div is the parent of the canvas. 2. Use instance mode and call noLoop() on the canvases that are not running.

Problems with option 1:
The best method I can find to do this would be to create a new script and add it to the DOM each time I want to switch the canvas, which seems like a bad solution. It also seems like using global mode may cause errors because remnants of the last program may still be in the global namespace. This method also means that the canvas will be reset if control is switched away from a file, then back.

Problems with option 2:
All the files are written assuming they use the global instance. I do not want to edit any of the files for two reasons: first, I will display the code later and I don’t want to store 2 versions, one for storing and one for displaying, and second, this could require changing tens of thousands of lines of code in separate files. This also seems like it might become very memory intensive if several sketches are loaded and kept in memory, even if they are not looping.

I also would prefer not to use iFrames if at all possible.

It seems like there is no good solution to this problem. Optimally, I would find a way to treat a js file as a single instance sketch, or find a way to dynamically switch which file a sketch is running from and reset that sketch.
It seems like this would be a fairly common use case, but I have spent the past few days searching and I can’t find a single good solution. Maybe I’m just bad at looking. :stuck_out_tongue:
If anyone has an answer or some input, I would much appreciate it.

Notes:
Only one canvas must be running at once.
Several of the sketches are reasonably intensive.
The sketches must appear in separate divs.
Which canvas is displayed will be controlled by a separate controller js file based on a numerical index assigned to each div.

1 Like

Closest sketch I have that you’re describing is this 1: :grinning:
https://CodePen.io/GoSubRoutine/pen/ZBPjdP/left/?editors=101

But it’s not working b/c a remote file it depends on doesn’t exist anymore. :crying_cat_face:

Why not? You can replace your div tags w/ iframe 1s: :wink:
https://GoSubRoutine.GitHub.io/Ball-in-the-Chamber/

2 Likes

Thank you for the suggestions.
I didn’t want to use iframes simply because they have caused me a large amount of hassle and annoyance in the past, so I didn’t even want to bother. However, after looking into it a little bit more, iframes may be the correct solution in this situation. If I were to use iframes, how would I go about pausing sketches when a new one is loaded? I have had issues with changing properties inside an iframe (from a script on the main webpage) before, but it might work better now since it is on the same domain. Would this be the option you suggest?
I also looked at your code pen example and I will play around with it a little bit more to see if it might be a good option for me.
Thank you for helping clear up some of my confusion and hesitancy to use iframes.

Assuming you have a variable iframe which points to the HTMLIFrameElement of the running sketch you wanna pause, you can call: iframe.contentWindow.noLoop();

Alternatively, the window property of each HTMLIFrameElement is stored in the frames[] pseudo-array:

Let’s say you wanna pause the sketch running at the 3rd created HTMLIFrameElement, you simply call: frames[2].noLoop();

2 Likes

That is perfect. Thank you for all the help.