Processing on the web

This page tries to explain how to quickly and (as) correctly (as possible) use Processing sketches on webpages. The information is based on the work done by the processing.js group.

This information on this page reflects the best of my knowledge anno March 2011, using Processing.js version 1.1, but as Processing.js becomes more and more complete, it is possible that the information on this page becomes outdated. Should you spot any incompletenesses or blatant mistakes, please contact me at pomaxҨnihongoresources.com, with the obvious substitutions in place to make it a legal email address.

If you're wondering about credentials: I'm a contributor/developer on the Processing.js project, and personally use it for vector graphics, and anything relating to that which might need a tutorial on the web, such as a detailed writeup on Bezier curves, a simple vector graphics application, playing with OpenType fonts by using Processing.js, and assorted other things.

What is Processing?

The "Processing" language (also referred to as "P5", think "Proce55ing") is a programming language (emphatically not "a program") with a focus on data visualisation. Of course, "data" is a loose concept, and Processing can be used for anything from drawing a few lines and circles on a screen, to full blown interactive animations. In fact, a basic Processing program is two lines of code, and will already play an animation:

	void setup() { size(..., ...); }
	void draw() {}

Of course this program doesn't show you anything, because all it does is set up the visual context to have a certain width and height (indicated in the setup method as the size(...,...) instruction) and then calls draw() every few milliseconds. Of course, draw() is empty, so it won't actually show you anything. A more useful minimal program would be a "hello world" program, but I hate those because they only show a programming language can write text, and that's pretty much the least interesting feature of any programming language. Instead let's look at a minimal program that makes sense for a data visualisation language:

play controls:
	float frame = 0;			// we start at frame 0
	float framerate = 24;		// our "sketch" will have a framerate of 24 frames per second.

	int ball_x;				// ball administration: x coordinate
	int ball_y;				// ball administration: y coordinate
	int ball_radius = 20;		// ball administration: ball radius

	void setup() {
	  size(200,200); 			// set draw area size
	  frameRate(framerate);	// set animation framerate
	  ball_x = width/2;		// set the initial ball coordinates
	  ball_y = ball_radius;		// set the initial ball coordinates
	  stroke(#003300);		// set the default shape outline colour
	  fill(#0000FF);			// set the default shape fill colour
	}

	void draw() {
	  frame++;											// note that we're one frame further than last time
	  float bounce_height = height/2 * abs(sin(PI*frame/framerate));	// compute the ball height for this frame
	  float ball_height = height - (bounce_height+ball_radius);		// because the top of the screen is 0, and the bottom is "height",
	  background(#FFFFEE);								// clear the drawing area
	  ball_y = (int) (ball_height);								// set the new ball y position
	  ellipse(ball_x,ball_y,ball_radius,ball_radius); 				// draw the ball
	}

This looks a bit long for a minimal program, but then again, this actually does something: it shows us a ball that bounces up and down, taking one second for each bounce. It shows a few aspects of Processing too: every variable is strongly typed. So you have to indicate what you'll be using a variable for, and you can choose from:

And of course there are also the typical complex data types:

You'll see why this last one turns out to be really useful later on.

Coming back to the minimally functional example of a Processing program, or "sketch", there are also some examples of Processing' own API at work. The following methods are native Processing calls:

The Processing API is in fact quite expansive (See http://processing.org/reference for the full list), but it can't cover everything. Luckily it supports object oriented programming, so that our previous example can also be written as an object oriented sketch:

play controls:
	Bouncer bouncer;

	void setup() {
	  size(200,200);
	  frameRate(24);
	  stroke(#003300);
	  fill(#0000FF);
	  bouncer = new Ball(width/2,20,20);
	}

	void draw() {
	  bouncer.computeNextStep(width, height, frameRate);
	  background(#FFFFEE);
	  bouncer.draw();
	}

	interface Bouncer {
		void computeNextStep(int width, int height, float framerate);
		void draw(); }

	class Ball implements Bouncer
	{
	  int x,y,radius;
	  int step=0;

	  Ball(int x, int y, int r) {
		this.x = x;
		this.y = y;
		this.radius = r;  }

	  void computeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		step++;
		float sin_value = abs(sin(PI*step/(float)frame_rate));
		float bounce_height = sketch_height/2 * sin_value;
		float ball_height = sketch_height - (bounce_height + radius);
		y = (int) (ball_height); }

	  void draw() { ellipse(x,y,radius,radius); }
	}

Instead of doing everything in the draw() function, the object oriented approach tucks all the code that relates to computing the ball's position in the definition for what we consider a "Ball". To be good object oriented programmers, we've also said that things that are a Ball are also a Bouncer, and this lets us extend our sketch very easily to instead of a bouncing ball, have a bouncing box by keeping almost everything the same, and adding a new class Box that's a Bouncer:

play controls:
	void setup() {
	  ...
	  bouncer = new Box(width/2,20,20,20);
	}

	class Box implements Bouncer
	{
	  int x,y,w,h;
	  int step=0;

	  Box(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h; }

	  void computeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		step++;
		float sin_value = abs(sin(PI/2.0 + (PI*step/(float)frame_rate)));
		float bounce_height = sketch_height/2 * sin_value;
		float ball_height = sketch_height - (bounce_height + h);
		y = (int) (ball_height); }

	  void draw() { rect(x,y,w,h); }
	}

All of a sudden we have a bouncing box, that starts from a falling position instead of from the ground, and we didn't have to modify the master draw() function for it! In fact, let's just use a group of bouncing things:

play controls:
	Bouncer[] bouncer = new Bouncer[3];

	void setup() {
	  ...
	  bouncer[0] = new Ball(width/3-20,20,20);
	  bouncer[1] = new Box(width/2-10,20,20,20);
	  bouncer[2] = new Ball((2*width/3)+20,20,20);
	}

	void draw() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].computeNextStep(width, height, frameRate); }
	  background(#FFFFEE);
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].draw(); }
	}

	...

Fantastic, two bouncing balls and a bouncing box, bouncing counter-point to each other. But it's not very interactive yet. Let's change it so that we can "hang on" to bouncing things until we let go of them again. Processing allows interaction with the keyboard and mouse, using what are known as "event handlers", methods that Processing automatically calls for you when you use the keyboard or mouse. In this case we care about mouse interaction, so we'll look at mousePressed and mouseReleased events:

play controls:
	...

	void mousePressed() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		if(bouncer[b].mouseOver(mouseX, mouseY)) {
		  bouncer[b].mousePressed(); }}
	}

	void mouseReleased() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].mouseReleased(); }
	}

	abstract class Bouncer
	{
		int x, y;
		boolean canmove = true;
		int step = 0;
		abstract void computeNextStep(int width, int height, float framerate);
		abstract void draw();
		abstract boolean mouseOver(int mx, int my);
		void mousePressed() { canmove = false; }
		void mouseReleased() { canmove = true; }
	}

	class Ball extends Bouncer
	{
	  int radius;

	  Ball(int x, int y, int r) {
		this.x = x;
		this.y = y;
		this.radius = r;  }

	  void computeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		if(canmove) {
		  step = (int)((step+1) % frame_rate);
		  float sin_value = abs(sin(PI*step/(float)frame_rate));
		  float bounce_height = sketch_height/2 * sin_value;
		  float ball_height = sketch_height - (bounce_height + radius);
		  y = (int) (ball_height); }}

	  void draw() { ellipse(x,y,radius,radius); }

	  boolean mouseOver(int mx, int my) {
		return sqrt((x-mx)*(x-mx) + (y-my)*(y-my)) <= radius; }
	}

	class Box extends Bouncer
	{
	  int w,h;
	  int step=0;

	  Box(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h; }

	  void computeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		if(canmove) {
		  step = (int)((step+1) % frame_rate);
		  float sin_value = abs(sin(PI/2.0 + (PI*step/(float)frame_rate)));
		  float bounce_height = sketch_height/2 * sin_value;
		  float ball_height = sketch_height - (bounce_height + h);
		  y = (int) (ball_height); }}

	  void draw() { rect(x,y-h/2,w,h); }

	  boolean mouseOver(int mx, int my) {
		return x<=mx && mx<=x+w && (y-h/2)<=my && my<=(y+h/2); }
	}

Because the Ball and Box classes will do the same thing on mouse interaction, the interface Bouncer has been changed to an actual class too, to take care of some of the shared functionality. Now if you click on anything that's a Bouncer it'll stop moving until you let it go. Let's go one step further an just allow us to move the bouncing things around, too.

play controls:
	Bouncer[] bouncer = new Bouncer[3];

	void setup() {
	  size(200,200);
	  frameRate(24);
	  stroke(#003300);
	  fill(#0000FF);
	  bouncer[0] = new Ball(width/3-20,20,20);
	  bouncer[1] = new Box(width/2-10,20,20,20);
	  bouncer[2] = new Ball((2*width/3)+20,20,20);
	}

	void draw() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].computeNextStep(width, height, frameRate); }
	  background(#FFFFEE);
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].draw(); }
	}

	void mousePressed() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		if(bouncer[b].mouseOver(mouseX, mouseY)) {
		  bouncer[b].mousePressed(); }}
	}

	void mouseReleased() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].mouseReleased(); }
	}

	void mouseDragged() {
	  for(int b=0, end=bouncer.length; b<end;b++) {
		bouncer[b].mouseDragged(mouseX, mouseY); }
	}

	abstract class Bouncer
	{
		int x, y;
		boolean canmove = true;
		int step = 0;
		int xoffset = 0;
		int yoffset = 0;

		void computeNextStep(int width, int height, float framerate) {
		  if(canmove) {
			reallyComputeNextStep(width, height, framerate); }}

		abstract void reallyComputeNextStep(int width, int height, float framerate);

		abstract void draw();

		abstract boolean mouseOver(int mx, int my);

		void mousePressed() {
		  canmove = false; }

		void mouseReleased() {
		  canmove = true;
		  x += xoffset;
		  y += yoffset;
		  xoffset = 0;
		  yoffset = 0; }

		void mouseDragged(int mx, int my) {
		  if(!canmove) {
			 xoffset = mx-x;
			 yoffset = my-y; }}
	}

	class Ball extends Bouncer
	{
	  int radius;

	  Ball(int x, int y, int r) {
		this.x = x;
		this.y = y;
		this.radius = r;  }

	  void reallyComputeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		step = (int)((step+1) % frame_rate);
		float sin_value = abs(sin(PI*step/(float)frame_rate));
		float bounce_height = sketch_height/2 * sin_value;
		float ball_height = sketch_height - (bounce_height + radius);
		y = (int) (ball_height); }

	  void draw() { ellipse(x+xoffset,y+yoffset,radius,radius); }

	  boolean mouseOver(int mx, int my) {
		return sqrt((x-mx)*(x-mx) + (y-my)*(y-my)) <= radius; }
	}

	class Box extends Bouncer
	{
	  int w,h;
	  int step=0;

	  Box(int x, int y, int w, int h) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h; }

	  void reallyComputeNextStep(int sketch_width, int sketch_height, float frame_rate) {
		step = (int)((step+1) % frame_rate);
		float sin_value = abs(sin(PI/2.0 + (PI*step/(float)frame_rate)));
		float bounce_height = sketch_height/2 * sin_value;
		float ball_height = sketch_height - (bounce_height + h);
		y = (int) (ball_height); }

	  void draw() { rect(x+xoffset,(y-h/2)+yoffset,w,h); }

	  boolean mouseOver(int mx, int my) {
		return x<=mx && mx<=x+w && (y-h/2)<=my && my<=(y+h/2); }
	}

And with that, on to the original topic of this article: using Processing on web pages

Putting a sketch on the page

The great thing about Processing is that it can be used on webpages. Traditionally, you would convert your sketch to a java applet, and embed that on a page, but the processing.js project has changed this: you can now use your sketches directly without turning it into an applet at all. In the same way that you include a javascript file, or a CSS stylesheet, you can simply link to your sketch and magic happens.

Let's say we save the previous sketch, with the bouncing and the mouse interaction, as "mysketch.pde", and we want to show this on a webpage. Using processing.js, this is a trivially simple trick:

	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="processing.js"></script>
		</head>
		<body>
			<canvas id="mysketch" data-processing-sources="mysketch.pde"/></canvas>
		</body>
	</html>

And we're done. In fact, I went ahead and made sure this page already uses processing.js, and that there is a mysketch.pde to load. If you click on the play control for the sketch on the right, it will start running, and do exactly what you would expect it to do based on what it does when you run it from the Processing environment.

Putting a sketch inline on the page

While not recommended, you can also put your sketch directly on a page, much like how you can put javascript or CSS styles directly on a page. However, in order for processing.js to properly load your code, you'll need some extra help in the form of the "init.js" file that is included with the processing.js examples archive from the processing.js downloads page

	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="processing.js"></script>
			<script type="text/javascript" src="init.js"></script>
		</head>
		<body>
			<script type="application/processing" target="mysketch">
			void setup() { ... }
			void draw() { ...}
			class SomeClass {
				...
			}
			</script>
			<canvas id="mysketch"/></canvas>
		</body>
	</html>

There are several reasons for why this is not a very good practice, but the most important one is that this way you can't be sure whether or not you've written a bug-free sketch. By writing it directly on the page, you might in fact have written some buggy code, which you will then find is terribly hard to debug because the browser is not equiped with a debugger for Processing code. In fact, processing.js rewrites your sketch into pure javascript (using some terribly clever tricks that we won't go into), so even if when it tells you where the error is in a javascript debugger, it will tell you where it went wrong in the converted javascript object, not the actual place in your source code. So keep it as a separate file, and make sure to test your code in the Processing IDE!

Making your sketch and your page see each other

Just running a sketch on a page is fine, but the benefit of a webpage is that it offers the kind of user interaction that you can't get from within the sketch itself. Pretty buttons, text areas that fold away, pop up, etc. make it very attractive to have your sketch do all the animation graphicsy work, but have all the information about the sketch, as well as controls for it, on the webpage. This is entirely possible - in fact, the "stop" and "play" buttons for the sketch above are examples of javascript telling the sketch what to do. Because a webpage offers more than a plain sketch can, processing.js has a few special tricks up its sleeve, so that you can get the most out of your creative work. Arguably the most important of these is the "get the sketch" function:

	var mysketch = Processing.getInstanceById('mysketchid');

This is the pivotal function on the javascript side of things. It gives you a direct reference to your sketch, and everything in it, so that you can call any function and examine and modify any variable that is in the sketch.

Making javascript see your sketch

Let's say we have the following sketch:

	void setup() {
	  size(200,200);
	  noLoop();						// turn off animation, since we won't need it
	  stroke(#FFEE88);
	  fill(#FFEE88);
	  background(#000033);
	  text("",0,0);					// force Processing to load a font
	  textSize(24);					// set the font size to something big
	}

	void draw() { }

	void drawText(String t)
	{
	  background(#000033);
	  float twidth = textWidth(t);			// get the width for the text
	  text(t, (width-twidth)/2, height/2);	// place the text centered on the drawing area
	}

We can make this sketch draw a different text based on some text we have on our webpage, using javascript. This is in fact really easy: first, let's save this processing code as mysketch2.pde, and load it onto a page in the same way as earlier in the article. Then, we use javascript to ask for our sketch instance, after which we call the "drawText" function with some text that we get from the web page that the sketch is running on:

set text:
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="processing.js"></script>
			<script type="text/javascript">
				function drawSomeText(id) {
					var pjs = Processing.getInstanceById(id);
					var text = document.getElementById('inputtext').value;
					pjs.drawText(text); }
			</script>
		</head>
		<body>
			<canvas id="mysketchcanvasid" data-processing-sources="mysketch2.pde"/></canvas>
			<input type="textfield" value="my text" id="inputtext"/>
			<button onclick="drawSomeText('mysketchcanvasid')"/>
		</body>
	</html>

This has the same effect as the sketch that's running on the right. Simply fill in a bit of text, and hit the ▶ button to see the sketch render it on the drawing area.

So far so good, but what if we also want to make Processing code call javascript? In order for us to do so, while making sure the sketch keeps running both on your page an in the Processing environment, we have to do a bit more work

Making your sketch "see" javascript

You can't just stick plain javascript in your sketch and hope everything goes well because it's "on a web page". A better approach is to neatly separate your sketch and your on-page javascript, and ensure that whatever you want to do on your page runs through a javascript function. How do we do that? Let's say we have the following page:

	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="processing.js"></script>
		</head>
		<body>
			<canvas id="mysketch3" data-processing-sources="mysketch3.pde"/></canvas>
			<div id="coordinates">
				x/y: <input type="textfield" id="xcoord"/>/<input type="textfield" id="ycoord"/>
			</div>
		</body>
	</html>

And say we have the following sketch, which we'll save as mysketch3.pde:

	void setup() {
	  size(200,200);
	  stroke(255);
	  background(0);
	  noLoop(); }

	void draw() {
	  fill(0,0,0,40);
	  rect(-1,-1,width+2,height+2); }

	void mouseMoved() {
	  line(mouseX,0,mouseX,height);
	  line(0,mouseY,width,mouseY);
	  redraw(); }

As an exercise, let's try to get the mouse coordinates from that mouseMoved event onto the page. This means we'll need to define a javascript function that will do this for us:

	function showXYCoordinates(x, y) {
		document.getElementById('xcoord').value = x;
		document.getElementById('ycoord').value = x; }

And we'll need to make the sketch know that there is such a thing as javascript, and that it has this function:

	interface JavaScript {
	  void showXYCoordinates(int x, int y); }

	void bindJavascript(JavaScript js) {
	  javascript = js; }

	JavaScript javascript;

	void setup() { ...}
	void draw() { ... }
	void mouseMoved() {
	  ...
	  if(javascript!=null){
		javascript.showXYCoordinates(mouseX, mouseY); }}

What we've done is we've told Processing: "There are things that follow the JavaScript interface. This means that whatever else they can do, they'll have a function called "showXYCoordinates" and that function takes two arguments, both of type int." - of course, the sketch will not magically know our on-page javascript, so we also define a function that lets us tell the sketch what actually counts as javascript, which is what the bindJavascript(...) function is for.

This leaves us with needing to make sure that we really do tell the sketch what javascript is, which we'll do as follows on the page:

	var bound = false;

	function bindJavascript() {
		var pjs = Processing.getInstanceById('mysketch3');
		if(pjs!=null) {
			pjs.bindJavascript(this);
			bound = true; }
		if(!bound) setTimeout(bindJavascript, 250); }

	bindJavascript();

This defines a function that checks whether processing.js has loaded our sketch yet. If not, it tries again 250ms later. If the sketch is loaded, the reference to the sketch is used to tell it what "javascript" should be. This is achieved by virtue of processing.js trusting that you wrote valid code. As such, as long as you're on the javascript side of things, you can pass the sketch whatever you like, and the sketch will trust that it conforms to what the method says the type should be. In this case we pass the javascript "this" value (which refers to the global javascript environment for the current window), and tell processing "this thing conforms to your JavaScript interface, so it has loads of things but the only thing you need to be concerned about is whether or not it has a showXYCoordinates(int, int) function, which it does."

So, our final sketch looks like the sketch behaves like the sketch on the right, and our final page source looks like the following:

x/y coordinates: /
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="processing.js"></script>
			<script type="text/javascript">
				var bound = false;

				function bindJavascript() {
					var pjs = Processing.getInstanceById('mysketch3');
					if(pjs!=null) {
						pjs.bindJavascript(this);
						bound = true; }
					if(!bound) setTimeout(bindJavascript, 250); }

				bindJavascript();

				function showXYCoordinates(x, y) {
					document.getElementById('xcoord').value = x;
					document.getElementById('ycoord').value = y; }
			</script>
		</head>
		<body>
			<canvas id="mysketch3" data-processing-sources="mysketch3.pde"/></canvas>
			<div id="coordinates">
				x/y: <input type="textfield" id="xcoord"/>/<input type="textfield" id="ycoord"/>
			</div>
		</body>
	</html>

Passing complex objects from javascript to your sketch

This leaves us with one last topic that we need to cover, simply because it's so common: using javascript to get some data into a sketch. There are a number of ways in which to achieve this, so let's look at every way I can think of that achieves this goal.

Actually using Processing objects

One interesting thing that processing.js allows us to do is to create objects as we defined them in our sketch, in javascript, and then hand them over to the sketch to deal with. To give an example, let's use the following sketch, which lets you draw points by clicking with the mouse, and links up all the points with lines:

click to place points
	ArrayList points;

	ArrayList getPoints() { return points; }

	void setup() {
	  size(200,200);
	  points = new ArrayList(); 
	  noLoop();
	  stroke(255,0,0);
	  fill(255); }

	void draw() {
	  background(200,200,255);
	  for(int p=0, end=points.size(); p<end; p++) {
		Point pt = (Point) points.get(p);
		if(p<end-1) {
		  Point next = (Point) points.get(p+1);
		  line(pt.x,pt.y,next.x,next.y); }
		pt.draw(); }}

	void mouseClicked() {
	  points.add(new Point(mouseX,mouseY));
	  redraw(); }

	class Point {
	  int x,y;
	  Point(int x, int y) { this.x=x; this.y=y; }
	  void draw() { ellipse(x,y,10,10); }}
load points:

We can also make javascript place some points for us, automatically, by using the following javascript:

	function loadPoints(id, button) {
		var pjs = Processing.getInstanceById(id);
		var points = pjs.getPoints();
		points.add(new pjs.Point(10,10));
		points.add(new pjs.Point(10,190));
		points.add(new pjs.Point(190,190));
		points.add(new pjs.Point(190,10));
		pjs.draw(); }

Because processing.js turns the sketch into actual javascript, every class we defined in it can be created using new pjs.ClassName(arguments,...).

JSON

Another way to get data from javascript into a sketch is by way of a JSON description. JSON is particulary interesting because javascript can read a JSON text string and immediately turn it into a full-fledged javascript object. Let's look at our point-drawing sketch again, this time with a dedicated "addPoint" method:

	ArrayList points;

	void setup() {
	  size(200,200);
	  points = new ArrayList(); }

	void draw() {
	  background(200,200,255);
	  for(int p=0, end=points.size(); p<end; p++) {
		Point pt = (Point) points.get(p);
		if(p<end-1) {
		  Point next = (Point) points.get(p+1);
		  line(pt.x,pt.y,next.x,next.y); }
		pt.draw(); }}

	void mouseClicked() {
	  addPoint(mouseX,mouseY); }

	Point addPoint(int x, int y) {
	  Point pt = new Point(x,y);
	  points.add(pt);
	  return pt; }

	class Point {
	  int x,y;
	  Point(int x, int y) { this.x=x; this.y=y; }
	  void draw() {
		stroke(255,0,0);
		fill(255);
		ellipse(x,y,10,10); }}

Now what if -- instead of using mouse clicks, or predetermined javascript -- we want to load points based on some data on a remote server? We change our web page so that it can deal with JSON data from a remote server, and then make our javascript tell the sketch what to do:

load points:
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>My Processing Page</title>
			<script type="text/javascript" src="jquery.js"></script>
			<script type="text/javascript" src="processing.js"></script>
			<script type="text/javascript">
				function drawPoints(id) {
					var pjs = Processing.getInstanceById(id);
					var json = $.get("http://thatfunkysite.com/serving/json.asp");
					var data = eval("("+json+")");
					if(data) {
						// we know the JSON is an array of points, called "points"
						for(p=0, end=data.points.length; p<end; p++) {
							var point = data.points[p];
							pjs.addPoint(point.x, point.y); }}}
			</script>
		</head>
		<body>
			<canvas id="mysketch5" data-processing-sources="mysketch5.pde"/></canvas>
			<div id="controller"><button id="loadPoints" onclick="loadPoints('mysketch5')"/></div>
		</body>
	</html>

The JSON that gets loaded in the example sketch in this section is the following:

	{ 'points' : [ {'x': 10 , 'y': 10} , {'x': 190 , 'y': 10} , {'x': 190 , 'y': 190} , {'x': 10, 'y': 190} ] }

XML

Another favourite is the XML document. This is where the Processing data type "XMLElement" comes into play. Rather than trying to use javascript to parse the XML, we pass the xml data straight on to our sketch, which will know exactly what to do with it:

load points:
	function loadPoints(id, button) {
		button.disabled = "disabled";
		var pjs = Processing.getInstanceById(id);
		var xml = $.get("http://thatfunkysite.com/serving/getxml.php");
		pjs.buildFromXML(xml); }

And the handling in our sketch will look like this:

	void buildFromXML(String xml) {
	  XMLElement data = XMLElement.parse(xml);
	  XMLElement[] xmlpoints = data.getChildren();
	  for(int p=0, end=xmlpoints.length; p<end; p++) {
		XMLElement xmlpoint = xmlpoints[p];
		int x = xmlpoint.getIntAttribute("x");
		int y = xmlpoint.getIntAttribute("y");   
		points.add(new Point(x, y)); }
	  redraw(); }

If the xml thus loaded looks like the following snippet, the sketch will behave in the way the sketch on the right does:

	<xml>
		<point x='10' y='10'/>
		<point x='190' y='50'/>
		<point x='10' y='90'/>
		<point x='190' y='140'/>
		<point x='10' y='190'/>
	</xml>

SVG

A special kind of XML document is the SVG —Scalable Vector Graphics— document. What's special about it is that it already represents visual data, and Processing can load SVG XML natively.

drawing with SVG
	XMLElement svgxml;
	PShape ps;
	int x=0;
	int y=0;
	int xoffset=0;
	int yoffset=0;
	int xmark=0;
	int ymark=0;

	void setup() {
	  size(200,200);
	  noLoop(); }

	void draw() {
	  background(255);
	  stroke(0);
	  for(int px=0; px<width; px+=10) { line(px,0,0,px); }
	  for(int py=0; py<height; py+=10) { line(width,py,0,py+height); }
	  stroke(#000066);
	  for(int py=0; py<height;py+=10) { line(0,py,width,py); }
	  if(ps!=null) { shape(ps,x-xoffset,y-yoffset,200,200); }}

	void mousePressed() {
	  xmark = mouseX;
	  ymark = mouseY; }

	void mouseDragged() {
	  xoffset = xmark-mouseX;
	  yoffset = ymark-mouseY; 
	  redraw(); }

	void mouseReleased() {
	  if(xoffset!=0 || yoffset!=0) {
		x -= xoffset;
		y -= yoffset;
		xoffset=0;
		yoffset=0; }
	  else {
		XMLElement path = svgxml.getChild(0);
		path.setAttribute("fill",getNextColor());
		bindSVG(svgxml); }}

	String[] colors = {"#f0f8ff","#faebd7","#00ffff","...", ..., ... };
	int color_len = colors.length; 
	int current_color = 0;

	String getNextColor() {
	  current_color = (current_color+1)%color_len;
	  return colors[current_color]; }

	void buildFromSVG(String svg) {
	  svgxml = XMLElement.parser(svg);
	  bindSVG(svgxml); }

	void bindSVG(XMLElement svg) {
	  ps = new PShapeSVG(svgxml);
	  redraw(); }

This sketch will load the following SVG code, and allows you to click on the shape to change its color, or click-drag it to move it around:

	<svg width='200' height='200'>
		<path d='M 10 10 L 190 10 L 140 100 L 190 190 L 10 190 L 50 100 L 10 10 M 100 80 L 140 30 L 50 30 L 100 80 M 100 120 L 50 170 L 140 170 Z'/>
	</svg>

Javascript objects

One last thing you may want to pass to a sketch is a real javascript object. Say we have a physics library that we want to take advantage of in our sketch, and for Processing it's a .jar file, but there's a javascript version too. This thing lets us create a javascript "Physics" object that we can call functions on for computing momentum and force transfer when we make two things hit each other. Since processing.js does not support .jar libraries (because it's precompiled binary java class code, and pjs cannot unpack a jar file, reverse engineer the .java source, transform it to Processing API calls, then confirm all calls are supported) we'll use this convenient javascript library. But how to do this cleanly?

We have to do three things:

  1. Write an interface for the object we're using, so our sketch will know what it even is,
  2. use a javascript binding so that we can ask javascript to make these objects for us, and
  3. write a javascript function to make these objects for us.

So let's get cracking! First we determine which functions in the javascript Physics object we actually make use of. We could write an interface that has correct method signatures for every function in the library, but this would be overkill. After reviewing our code we see that we actually only make use of three of the objects functions: collide_objects(forcevector1, forcevector2, collisionangle), get_force_vector(startpoint, distancevector, accelleration) and get_trajectory(startpoint, objectmass, initialvector, gravityvector, gravitystrength). Let's build our interface:

	interface Physics
	{
		// collision modifies the two force vectors in place. Nothing is returned.
		void collide_objects(float[] forcevector1, float[] forcevector2, float collisionangle);

		// get force vector returns a force vector
		float[] get_force_vector(float[] startpoint, float[] distancevector, float accelleration);

		// trajectory calculation returns a curve, represented as a lest of 2D coordinates
		float[][] get_trajectory(float[] startpoint, float objectmass, float[] initialvector, float[] gravityvector, float gravitystrength);
	}

First job done. Now to bind javascript. We've already looked at how to do this, so just follow the standard procedure and job's a good'n. In addition to whatever javascript functions you want to expose, however, we must add one more:

	interface JavaScript {
		...
		Physics buildPhysicsObject([properly typed variables to match the javascript constructor]);
		...
	}

Finally, we now make use of our purely javascript library in our js file(s):

	function buildPhysicsObject(x, y, someothervar)
	{
		return new Physics(x,y,someothervar);
	}

This last step seems silly, but we have to delegate the task of building a javascript object to javascript. If we tried to do this inside our sketch, processing.js will not complain, but Processing will. To make matters worse, it also obscures the point of failure: if something goes wrong in the sketch, did it go wrong because processing.js has a bug, or because you were sloppy with javascript inside a Processing sketch? Golden rule: keep the different languages separated as much as possible.

We're almost set to use our javascript library for Processing purposes now. The only thing left is to create these objects and then use them in our sketch:

	class MassBody
	{
	  // a class for bodies with mass that travel with some speed and are located at some x/y position
	  float[] forceVector = new float[2]; // 2 dimensional vector;
	  int XDIM = 0;  // index constant
	  int YDIM = 1;  // index constant
	  float x = 0;  // position
	  float y = 0;  // position
	  MassBody(float x, float y) { forceVector[XDIM] = 0; forceVector[YDIM] = 0; this.x=x; this.y=y; }
	  void draw() { /* draws the body */ }
	  float[] getForce() { return forceVector; }
	  void impartForce(float[] stimulus) { forceVector[XDIM] += stimulus[XDIM]; forceVector[YDIM] += stimulus[YDIM]; }
	  void updatePosition() { x+=...; y+=...; }
	}

	MassBody body1 = new MassBody(...);
	MassBody body2 = new MassBody(...);

	Phsyics physicsObject
	
	void bindJavascript(JavaScript js) {
	  javascript = js; 
	  int x = 0;
	  float y = 9;
	  String[] somevalues = {"scalar", "vector", "tensor"};
	  physicsObject = javascript.buildPhysicsObject(x,y,somevalues);
	}

	void setup()
	{
	  ...
	}
	
	void draw()
	{
	  // if the two bodies collide, compute the resultant forces
	  if(body1.collides(body2))
	  {
		// forces are recomputed in place
		float angle_12 = body1.getAngleTo(body2);
		physicsObject.collide_objects(body1.getForce(), body2.getForce(), angle_12);
		body1.updatePosition();
		body2.updatePosition();
	  }
	  body1.draw();
	  body2.draw();
	}

And we're done!

Processing.js as javascript graphics library

As last point of business, you can of course also use Processing.js as a pure graphics library, by invoking it for some canvas and then calling Processing API calls directly. Let's jump right in! The following code is what you would write on-page, although of course as ever it's far better practice to link to your source files, so you should really place what's in the script tags in a file myPjsSketch.js and link to it using src="..." instead.

	<canvas id="glibcanvas"></canvas>
	<script type="text/javascript">
		(function(){
			var canvas = document.getElementById('glibcanvas');
			var pjs = new Processing(canvas, function(p) {});

This binds a new Processing instance to the indicated canvas. The function(p) {} bit is actually completely unimportant, but must be used until ticket 1,111 lands in Processing.js 1.2 (March 2011). Once 1.2 is out, the binding will simply be var pjs = new Processing(canvas).

			// let's write a sketch
			var value=0;

			// Definition for the initial entry point
			pjs.setup = function() {
				pjs.size(200,200);
				// we want to turn off animation, because this is a demo page and it
				// would use cpu while not being looked at. Only draw on mousemoves
				pjs.noLoop(); }

This setup() function defines the entry point for our sketch. It sizes the canvas, and tells it not to animate by default.

			// Draw a "sine wave" using two bezier curves, with an undulating amplitude.
			pjs.draw = function() {
				// partially clear, by overlaying a semi-transparent rect
				// with background color
				pjs.noStroke();
				pjs.fill(255,75);
				pjs.rect(0,0,200,200);

				// draw the "sine wave"
				pjs.stroke(100,100,200);
				pjs.noFill();
				pjs.bezier(0,100, 33,100+value, 66,100+value, 100,100);
				pjs.bezier(100,100, 133,100+-value, 166,100+-value, 200,100);
			}

The draw() function defines the main draw function, which is called whenever a frame update is requested (either because the sketch is looping, or because redraw() is called manually)

			pjs.mouseMoved = function() { 
				value = (pjs.mouseY-100);
				pjs.redraw(); }

The mouseMoved() function is a Processing event handler that is triggered by the mouse moving around over the canvas. It is far more convenient to use the built-in event handler than to write our own.

This is all we need in our sketch, so there's only one call left to make:

			// Finally, calling setup() will kickstart the sketch
			pjs.setup();
		})();
	</script>

This code will give you the sketch that can be found on the right of the code block - it draws a sinewave with an amplitude that depends on where the mouse is on the canvas.

HELP! Everything's gone wrong! How do I debug my code?

If you run into the problem that your processing.js sketch doesn't work, and you checked Firebug (for Firefox), Dragonfly (for Opera) or webkit developer tools (for Safari and Chrome) while running your sketch, but they didn't help you figure out what's going wrong, what should you do?

Following the next 11-step plan, you should be able to either fix things yourself, or if you make it to step 8, you have every right to come to our doorstep and ask us to fix whatever's wrong because there's a genuine problem with the Processing.js library!

Before you start

Before you start debugging, you want to make sure your code is in a state that will allow you to effectively debug it. The following three questions are intended to make sure you have done everything you need in order to use the tools required for prodding your code with the debugging stick.

0) Just to be sure, do you want your code to be correct?

yes: Great! skip to step (1)

no: We can't really help you until you do :(

1) Do you mix javascript and processing in your files?

yes: Skip to step (2).

no: Skip to step (3).

2) Did you make sure to keep the javascript and Processing code separate, and link them using an interface?

yes: Skip to step (3).

no: Read over Processing on the Web: making your sketch "see" javascript, and apply this to your source

Debugging

The following six steps will run you through the basic debugging and possible fixing steps when something goes wrong with your code. It is possible that while running through these steps you actually fix the problem you were having, in which case hurray! Your code is fixed! If, however, you get to step eight, there is a genuine problem and you'll want to move on to getting us involved.

3) Do your source files end in ".pde"?

yes: Skip to (4).

no: Rename them to ".pde". Processing.js doesn't care about the extension, but native Processing cares a great deal.

4) Your .pde files are in a directory/folder called [...], but is your main sketch (the one that contains setup) file called [...].pde?

yes: Skip to (5).

no: Make sure your main sketch has the same name as the directory/folder.

5) Do you have the Processing IDE (PDE)?

yes: Skip to (6).

no: Download it from http://processing.org/download and install it.

6) Start PDE and load your sketch.

7) When you tell PDE to run your code, does it run?

yes: Skip to (8).

no: Fix any error that PDE signals, then repeat this step.

8) Does this code also run when used with Processing.js?

yes: Hurray! Problem solved!

no: Reduce your code to a minimal example that still works in the Processing IDE, but goes wrong when using Processing.js, and read on...

Bringing it to our attention

At this point you've discovered a deficiency or bug with the Processing.js library, and we would very much like to hear from you so that we can fix it. The following three steps will make sure that we hear about it, so that we get the chance to improve compatibility between Processing and Processing.js.

9) If it works in Processing, but not in Processing.js, we screwed up! Do you use IRC?

yes: Drop by the #processing.js channel on irc.mozilla.org to let us know about it. Proceed to step (10).

no: If you've heard about IRC but never used it, now is an excellent time to start! Install an IRC client (there are many clients, but here are some common ones for windows, Mac OS X, GTK *nix, and terminal *nix) and visit our channel. However, if you are emphatically opposed to using IRC (which would be a shame), skip to step (11).

10) Is there anyone there to listen to you?

yes: Excellent. If things are properly wrong, we'll cover step (11) in the channel.

no: Skip to step (11).

11) File a ticket with your minimal example on lighthouse at: https://processing-js.lighthouseapp.com/projects/41284-processingjs

More information

For more information, you can visit the following websites, or visit us in the #processing IRC channel on irc.mozilla.org

This article was written by Mike "Pomax" Kamermans from nihongoresources.com. You can contact me at the fairly simple "pomax@" prefixed to the just mentioned domain, or just drop by the IRC channel for a more immediate kind of dialog.