2

I've recently made the leap from using Khan Academy's processing.js environment to the real deal and am getting a little confused.

I have a simple processing.js program that basically draws a circle, and I want the size of this circle to be determined by the width of the canvas.

If I print the width within a processing.js function, like setup, I'm shown the correct 500px width. Unfortunately, whenever I try to access the width property outside of a processing.js function, it shows the default 100px size, even though the canvas itself is 500px wide.

I think I might be using a fairly ugly mix of processing and javascript, which could be the root of my problems. Your help would be much appreciated!

Processing.js

///* PROCESSING.JS SETUP *///
void setup() {
    size(500, 500);
    println(width); // WORKS! :)
}

println(width); // DOESN'T WORK... :(

///* GLOBAL VARIABLES *///
var moleculeQuantity = 1;

///* OBJECT CONSTUCTORS *///
var Molecule = function(x, y) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
};

Molecule.prototype.draw = function() {
    noStroke();
    fill(88, 91, 183);
    ellipse(this.x, this.y, 70, 70);

    fill(225, 227, 228);
    ellipse(this.x, this.y, 40, 40);
};

// Fill array with molecule objects
var molecules = [];
for (var i = 0; i < moleculeQuantity; i++) {
    molecules[i] = new Molecule(200, 100);
}

///* DRAW FUNCTION *///
void draw() {
    background(225, 227, 228);
    molecules[0].draw();
}
2
  • 1
    write var width; somewhere in the global scope? Commented Jan 7, 2016 at 17:19
  • Thanks Jeremy, but @Kevin has pointed out why this won't necessarily work below. The globally declared width still remains undefined until the setup function is called. Commented Jan 13, 2016 at 17:02

1 Answer 1

3

Your problem has nothing to do with mixing Processing and JavaScript, and it has nothing to do with asynchronous execution. It's much simpler than that.

Think of the order your code executes in. Anything outside of a method will execute before your setup() function is called. In your case, that means you're accessing the width variable before you've changed it by calling the size() function.

You have to change your code so that your code is triggered after setup() is called. The simplest way to do that is to just move your code to the end of your setup() function, or into a function that's called after setup(), such as the draw() or event methods.

You might think that because your function call is below the setup() function in your code that the setup() call happens first, but it doesn't. You've simply defined the setup() function- it hasn't been called (by Processing) yet! Try moving any code that's outside of a function to the top of your sketch to make it more obvious:

println(width); // this happens first, so width is still 100

void setup() {
    size(500, 500);
    println(width); //now that size() has been called, the width is 500
}

Edit: I'll try to explain the order of events. Here is what happens when you load a page that contains a Processing.js sketch:

  1. The page is loaded.
  2. Processing.js itself is loaded.
  3. Processing.js compiles your Processing code into JavaScript code.
  4. Your code (which is now JavaScript code) is loaded. Functions like setup() and draw() are defined at this step, but not called yet. Code outside of your functions is called. This is when you see 100 being printed out.
  5. Processing.js calls the setup() function that was defined in step 4. This is when the width is set.
  6. Processing.js starts calling the draw() function 60 times per second.

As for where you should place your variables and functions, that completely depends on what you want to do with them. But you might place a variable's declaration at the top of your sketch and its initialization inside the setup() function. That way you can access its value anywhere, but you know it won't be set until setup() has run. Something like this:

float middleX;

void setup(){
   size(500, 500);
   middleX = width/2;
}

void draw(){
   background(0);
   ellipse(middleX, mouseY, 10, 10);
}
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks Kevin, that makes a lot of sense. I thought processing.js compiled into javascript before running, and I presumed that the first thing it would need to do is execute the setup function. Are you saying that processing.js generally executes its functions after hoisting my javascript, or does it just so happen that the setup function is executed later? In this case, where should I place my constructors and global variables when they will require 'width'? Wouldn't placing them in the setup function localise their scope? Thanks again for helping me out.
Also, I just checked the processing.js documentation, and it says that setup() is called once when the program is started. Now I'm very confused. If setup() is called when the program is started, why doesn't it immediately set the width variable?
@curzmg Check out my edit and let me know if you have any other questions.
Great edit - that's cleared up the order of operations for me. I'm sure there's a perfectly good reason for it, but it seems a little frustrating that such crucial variables aren't available from the start. Oh well, I'm sure I can figure something out. Thank you for taking the time.
@curzmg They aren't available at start for the same reason that mouseX and mouseY aren't available before you move the mouse into the window. It doesn't make sense to ask Processing for the mouse position before the mouse has a position, and it doesn't make sense to ask Processing for the size before the sketch has a size. Any problems caused by this can be resolved by simply moving the initialization of whatever variables to the end of the setup() function.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.