Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically "unload" a Processing JS sketch from canvas

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.

like image 379
Andrew Marconi Avatar asked Jun 24 '12 14:06

Andrew Marconi


2 Answers

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;
};
like image 145
Andrew Marconi Avatar answered Sep 28 '22 03:09

Andrew Marconi


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.

like image 30
Darshan Rivka Whittle Avatar answered Sep 28 '22 05:09

Darshan Rivka Whittle