Dynamically "unload" a Processing JS sketch from canvas
Asked Answered
E

3

8

I'm using some javascript to allow users to dynamically load a sketch on click to a canvas element using:

Processing.loadSketchFromSources('canvas_id', ['sketch.pde']);

If I call Processing.loadSketchFromSources(...) a second (or third...) time, it loads a second (or third...) .pde file onto the canvas, which is what I would expect.

I'd like for the user to be able to click another link to load a different sketch, effectively unloading the previous one. Is there a method I can call (or a technique I can use) to check if Processing has another sketch running, and if so, tell it to unload it first?

Is there some sort of Processing.unloadSketch() method I'm overlooking? I could simply drop the canvas DOM object and recreate it, but that (1) seems like using a hammer when I need a needle, and (2) it results in a screen-flicker that I'd like to avoid.

I'm no JS expert, but I've done my best to look through the processing.js source to see what other functions may exist, but I'm hitting a wall. I thought perhaps I could look at Processing.Sketches.length to see if something is loaded already, but simply pop'ing it off the array doesn't seem to work (didn't think it would).

I'm using ProcessingJS 1.3.6.

Emogene answered 24/6, 2012 at 14:54 Comment(0)
H
0

As of processing.js 1.4.8, Andrew's accepted answer (and the other answers I've found in here) do not seem to work anymore.

This is what worked for me:

    var pjs = Processing.getInstanceById('pjs');
    if (typeof pjs !== "undefined") {
      pjs.exit();
    }

    var canvas = document.getElementById('pjs')
    new Processing(canvas, scriptText);

where pjs is the id of the canvas element where the scrips is being run.

Hulett answered 23/6, 2017 at 14:43 Comment(2)
Sorry to contradict this, but code in the question seems to work in 1.4.8 and this answer does not appear to work.Campbellbannerman
I'm really far away from this and i cannot really tell you more than what I wrote above. All I can say: there is no code in the question... so i cannot really check if your comment is correct or not.Hulett
E
5

In case someone else comes looking for the solution, here's what I did that worked. Note that this was placed inside a closure (not included here for brevity) -- hence the this.launch = function(), blah blah blah... YMMV.

/**
 * Launches a specific sketch. Assumes files are stored in
 * the ./sketches subdirectory, and your canvas is named g_sketch_canvas
 * @param {String} item The name of the file (no extension)
 * @param {Array} sketchlist Array of sketches to choose from
 * @returns true
 * @type Boolean
 */
this.launch = function (item, sketchlist) {
    var cvs = document.getElementById('g_sketch_canvas'),
        ctx = cvs.getContext('2d');
    if ($.inArray(item, sketchlist) !== -1) {
        // Unload the Processing script
        if (Processing.instances.length > 0) {
            // There should only be one, so no need to loop
            Processing.instances[0].exit();
            // If you may have more than one, then use this loop:
             for (i=0; i < Processing.instances.length; (i++)) {
            //  Processing.instances[i].exit();
            //}
        }
        // Clear the context
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        ctx.clearRect(0, 0, cvs.width, cvs.height);
        // Now, load the new Processing script
        Processing.loadSketchFromSources(cvs, ['sketches/' + item + '.pde']);
    }
    return true;
};
Emogene answered 26/6, 2012 at 2:54 Comment(3)
Nice work answering your own question. Welcome to Stack Overflow :)Eddings
Hi im having a problem, Processing.instances.length is returning (0) even though i have 2 sketches running well on my web page. Did u have to populate Processing.instances when loading a sketch prior to the unload function?Fuscous
Also this ticket seems to be important here: processing-js.lighthouseapp.com/projects/41284-processingjs/…Fuscous
K
3

I'm not familiar with Processing.js, but the example code from the site has this:

var canvas = document.getElementById("canvas1");
// attaching the sketchProc function to the canvas
var p = new Processing(canvas, sketchProc);
// p.exit(); to detach it

So in your case, you'll want to keep a handle to the first instance when you create it:

var p1 = Processing.loadSketchFromSources('canvas_id', ['sketch.pde']);

When you're ready to "unload" and load a new sketch, I'm guessing (but don't know) that you'll need to clear the canvas yourself:

p1.exit();
var canvas = document.getElementById('canvas_id'); 
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// Or context.fillRect(...) with white, or whatever clearing it means to you

Then, from the sound of things, you're free to attach another sketch:

var p2 = Processing.loadSketchFromSources('canvas_id', ['sketch2.pde']);

Again, I'm not actually familiar with that library, but this appears straightforward from the documentation.

Kashmiri answered 25/6, 2012 at 9:33 Comment(1)
Thanks for answering.. it got me 75% there... There are two "modes" of using Processing in Javascript: (1) load up a processing .pde file dynamically, or (2) write your Processing script within JS. The 'fatal flaw' is that .loadSketchFromSources() doesn't seem to return a usable handle. Instead, you have to look at Processing.instances.length to determine that one is currently running. If so, you can call Processing.instances[0].exit()... provided there's only one script running. (Sorry, I can't +1 your answer -- I don't have enough pts for that yet).Emogene
H
0

As of processing.js 1.4.8, Andrew's accepted answer (and the other answers I've found in here) do not seem to work anymore.

This is what worked for me:

    var pjs = Processing.getInstanceById('pjs');
    if (typeof pjs !== "undefined") {
      pjs.exit();
    }

    var canvas = document.getElementById('pjs')
    new Processing(canvas, scriptText);

where pjs is the id of the canvas element where the scrips is being run.

Hulett answered 23/6, 2017 at 14:43 Comment(2)
Sorry to contradict this, but code in the question seems to work in 1.4.8 and this answer does not appear to work.Campbellbannerman
I'm really far away from this and i cannot really tell you more than what I wrote above. All I can say: there is no code in the question... so i cannot really check if your comment is correct or not.Hulett

© 2022 - 2024 — McMap. All rights reserved.