P5 and Browserify

edited September 2015 in p5.js

I'm having some scope issues when I attempt to use p5.js with Browserify.

I have browserify-shim transforming global:p5 to a p5 variable I can require, which I'm doing. Most methods work great if I have a structure like this:

var p5 = require('p5');

var newp5 = new p5(function(sketch) {

  sketch.setup = function() {
    img = sketch.loadImage('/path/to/img');

}


}, 'dom-elem');

The problem I'm encountering is that certain methods, i.e. the methods that seem to only work when called via dot notation, don't work inside Browserify. So, for example, where I might normally use:

x = 100;
y = 90;
img.get(x,y);

to get pixel data for those coordinates in the image, I can't when using Browserify - I get an "undefined" error. I'm sure this is just an issue of scope - the dot notation must be stringifying some variable along the way, but I can't figure out the correct syntax.

Answers

  • Ah, so I figured this out - it's not a scope issue at all, but rather an issue with the time it takes to load the image from within Browserify vs from without. Moving all my functionality inside the loadImage success callback fixed the issue:

    var p5 = require('p5');
    
    var newp5 = new p5(function(sketch) {
    
      sketch.setup = function() {
        sketch.loadImage('/path/to/img', function(img) {
               x = 100;
               y = 90;
              img.get(x,y);
        });
    
    }
    
    
    }, 'dom-elem');
    

    works like a champ.

  • edited September 2015 Answer ✓

    Dunno much about browserify and other similar JS loaders.
    But AFAIK, when we don't pass a "sketch" function to p5's constructor, it assumes it's in "global" mode and copies everything to JS' window:

    https://GitHub.com/processing/p5.js/blob/master/src/core/core.js#L441

    // If the user has created a global setup or draw function,
    // assume "global" mode and make everything global (i.e. on the window)
    if (!sketch) {
      this._isGlobal = true;
      // Loop through methods on the prototype and attach them to the window
      for (var p in p5.prototype) {
        if(typeof p5.prototype[p] === 'function') {
          var ev = p.substring(2);
          if (!this._events.hasOwnProperty(ev)) {
            window[p] = p5.prototype[p].bind(this);
          }
        } else {
          window[p] = p5.prototype[p];
        }
      }
      // Attach its properties to the window
      for (var p2 in this) {
        if (this.hasOwnProperty(p2)) {
          window[p2] = this[p2];
        }
      }
    
    } else {
      // Else, the user has passed in a sketch closure that may set
      // user-provided 'setup', 'draw', etc. properties on this instance of p5
      sketch(this);
    }
    

    The problem as you noticed, that code block is hardwired to window[p].

    Perhaps you should try your luck there and request some new p5's constructor object parameter to replace default window: [-O< https://github.com/processing/p5.js/issues

    Mention this forum thread so they have a better idea what's being asked. :-\"

  • edited September 2015

    Oh, I thought you were trying to emulate "global mode" via browserify w/o actually use the regular "instance mode".

    Seems like you were just avoiding creating even 1 single variable in the global scope.

    Just know that we don't need any variables in order to to call p5's constructor.

    Just a simple new p5( function(p) { } ) is enough to ignite it. No browserify is needed! :-@

  • Yeah, I'm already using browserify, and I need all my site's JS to be in browserify so I'm copying the window.p5 object into browserify's closure which is why I have to pass a variable in the constructor - otherwise none of the methods work at all. Initially I couldn't figure out why my proof of concept worked great but the same code inside browserify didn't, and I thought it was a scope issue but it turns out that loadImage takes longer to execute inside browserify's closure and so my img variable was undefined. Moving all the code to be executed to inside the loadImage success callback fixed the issue.

  • edited September 2015 Answer ✓

    Since you were asking about browserify, I haven't paid attention you were calling loadImage() inside setup() w/o passing a callback to it: b-( http://p5js.org/reference/#/p5/loadImage

    Framework p5js provides a preload() callback so we can load resources w/o passing callback parameters to them: *-:) http://p5js.org/reference/#/p5/preload

    In short, your "bug" had nothing to do w/ browserify but lacking of callbacks or preload().

    In some cases, loadImage() can execute its task fast enough that it ends up working w/o a callback.
    But that it's unpredictable behavior and we shouldn't rely on it! [-X

Sign In or Register to comment.