Web-Drawing Throwdown: Paper.js Vs. Processing.js Vs. Raphael

Do
you need to support older browsers?
If the answer is yes, then your only choice isRaphaël. It handles browsers all the way back to IE 7 and Firefox 3. Raphaël even has some support for IE 6, although some of its underlying technology cannot be implemented
there.

Do
you need to support Android?
Android doesn’t support SVG, so you’ll have to use Paper.js or Processing.js. Some rumors say that Android 4 will handle SVG, but the majority of Android devices won’t
support it for years.

Is
your drawing interactive?
Raphaël and Paper.js focus on interaction with drawn elements through clicking, dragging and touch. Processing.js doesn’t support any object-level events, so responding to user gestures is very difficult. Processing.js can draw a cool animation on your home
page, but the other tools are better for interactive applications.

Paper.js, Processing.js and Raphaël are the leading libraries for drawing on the Web right now. A couple of others are up and coming, and you can always use Flash, but these three work well with HTML5 and have the widest support among browser vendors.

Choosing the right framework will determine the success of your project. This article covers the advantages and disadvantages of each, and the information you need to make the best choice.

All of the code in this article is open source and can be run on the demo page that accompanies this article.

[Note:
Have you already pre-ordered your copy of our Printed
Smashing Book #3? The book is a professional guide on how to redesign websites and it also introduces a whole new mindset for progressive Web design, written by experts for you.]

Overview

Paper.js

Processing.js

Raphaël

Technology

canvas tag

canvas tag

SVG

Language

PaperScript

Processing script

JavaScript

Browsers

IE 9

IE 9

IE 7

Mobile

Yes

Yes

iOS only

Model

Vector and raster

Raster

Vector

Size

56 KB

64 KB

20 KB

It’s all JavaScript once the page runs, but the frameworks take different paths to get there. Raphaël is written directly in JavaScript, but Paper.js uses PaperScript, and Processing.js uses its own script. They all support Firefox, Chrome and Safari, but Internet
Explorer is an issue — Paper.js and Processing.js use the canvas tag
and thus require IE 9.

PaperScript is a JavaScript extension that makes it possible to write scripts that don’t pollute the global namespace. This cuts down on JavaScript conflicts. PaperScript also supports direct math on objects such as Point and Size:
you can add two points together as if they were numbers.

Processing.js is based on a framework named Processing, which runs in the Java Virtual Machine. You define int and float instead
of var,
and you can use classes with Java-style inheritance. While the Processing.js script looks a little like Java, it’s more like JavaScript and doesn’t require many of the more complex features of Java.

Using all three libraries is easy if you have some familiarity with JavaScript.

Getting Started

Start by importing each library. The process for setting each up is a little different.

SETTING UP PROCESSING.JS

Processing.js uses the data-processing-sources attribute
of the canvas tag
to import your drawing. I use a .java extension
for Processing’s source file so that my editor color-codes it properly. Some authors use a .pde or .pjs extension.
It’s up to you.

SETTING UP RAPHAËL

Raphaël is imported like any other JavaScript file. It works well with jQuery’s ready function
or any other JavaScript framework.

Now we can start drawing.

Object-Oriented Drawing

Both Paper.js and Raphaël use object-oriented drawing: you draw a circle and get back a circle object. Processing.js draws the circle and doesn’t give you anything back. The following simple example makes it clear. Let’s start with a circle in the middle of
the screen at point 100,100.

Paper.js:

1

varcircle
= newPath.Circle(newPoint(100,
100), 10);

2

circle.fillColor
= '#ee2a33';

Raphaël:

1

varpaper
= Raphael('raphaelCircle',
200, 200);

2

varc
= paper.ellipse(100, 100, 10, 10);

3

c.attr({'fill':'#00aeef','stroke':'#00aeef'});

Processing.js:

01

void
setup() {

02

size(200,
200);

03

}

04

05

void
draw() {

06

background(#ffffff);

07

translate(100,
100);

08

fill(#52b755);

09

noStroke();

10

ellipse(0,
0, 20, 20);

11

}

Each code snippet draws the same circle. The difference is in what you can do with it.

Paper.js creates the circle as a path object. We can hold onto the object and change it later. In Paper.js, circle.fillColor
= 'red'; fills our circle with red, and circle.scale(2) makes
it twice as big.

Raphaël follows Paper.js’ object-oriented model. In Raphaël, we can change the color of our circle with circle.attr('fill',
'red');, and scale it up with circle.scale(2,
2);. The point is that the circle is an object that we can work with later.

Processing.js doesn’t use objects; the ellipse function
doesn’t return anything. Once we’ve drawn our circle in Processing.js, it’s part of the rendered image, like ink on a page; it’s not a separate object that can be changed by modifying a property. To change the color, we have to draw a new circle directly on
top of the old one.

When we call fill,
it changes the fill color for every object we draw thereafter. After we calltranslate and fill,
every shape will be filled with green.

Because functions change everything, we can easily end up with unwanted side effects. Call a harmless function, and suddenly everything is green! Processing.js provides the pushMatrix andpopMatrix functions
to isolate changes, but you have to remember to call them.

Processing.js’ no-objects philosophy means that complex drawings run faster. Paper.js and Raphaël contain references to everything you draw, and so the memory overhead created by complex animations will slow down your application. Processing.js contains no
references to drawn elements, so each shape takes up a tiny amount of memory. Memory overhead pays off if you need to access an object later, but it’s overkill if you don’t. Paper.js gives you a way out of this with theSymbol object
and by rasterizing objects, but you have to plan ahead to keep the app running fast.

The object-oriented versus no-objects philosophy has implications for everything you do with these libraries. It shapes the way each library handles animations.

Let’s Make It Move

Rotating circles aren’t very interesting, so we’ll make a square rotate around a circle.

ANIMATION IN PROCESSING.JS

Processing.js supports animation with the predefined setup and draw functions,
like this:

01

float
angle = 0.0;

02

void
setup() {

03

size(200,
200);

04

frameRate(30);

05

}

06

07

void
draw() {

08

background(#ffffff);

09

translate(100,
100);

10

fill(#52b755);

11

noStroke();

12

ellipse(0,
0, 20, 20);

13

14

rotate(angle);

15

angle
+= 0.1;

16

noFill();

17

stroke(#52b755);

18

strokeWeight(2);

19

rect(-40,
-40, 80, 80);

20

}

The setup function
is called once when the application starts. We tell Processing.js to animate with a frame rate of 30 frames per second, so our draw function
will be called 30 times every second. That rate might sound high, but it’s normal for making an animation look smooth.

The draw function
starts by filling in the background of the canvas;
it paints over anything left over from previous invocations of the draw function.
This is a major difference with Processing.js: we are not manipulating objects, so we always have to clean up previously drawn shapes.

Next, we translate the coordinate system to the 100,100 point.
This positions the drawing at 100 pixels from the left and 100 pixels from the top of the canvas for every drawing until we reset the coordinates. Then, we rotate by the specified angle. The angle increases with every draw,
which makes the square spin around. The last step is to draw a square using the fill and rect functions.

The rotate function
in Processing.js normally takes radians instead of degrees. That’s why we increase the angle of each frame by 0.2, rather than a
higher number such as 3. This is one of many times when trigonometry shows up in this method of drawing.

ANIMATION IN PAPER.JS

Paper.js makes this simple animation easier than in Processing.js, with a persistent rectangle object:

01

varr;

02

03

functioninit()
{

04

varc
= newPath.Circle(newPoint(100,
100), 10);

05

c.fillColor
= '#ee2a33';

06

07

varpoint
= newPoint(60,
60);

08

varsize
= newSize(80,
80);

09

varrectangle
= newRectangle(point,
size);

10

r
= newPath.Rectangle(rectangle);

11

r.strokeColor
= '#ee2a33';

12

r.strokeWidth
= 2;

13

}

14

15

functiononFrame(event)
{

16

r.rotate(3);

17

}

18

19

init();

We maintain the state of our square as an object, and Paper.js handles drawing it on the screen. We rotate it a little for each frame. Paper.js manages the path, so we don’t have to redraw everything for each frame or keep track of the angle of rotation or
worry about affecting other objects.

ANIMATION IN RAPHAËL

Animations in Raphaël are written in standard JavaScript, so Raphaël doesn’t have specific functions for handling animation frames. Instead, we rely on JavaScript’s setInterval function.

01

varpaper
= Raphael('raphaelAnimation',
200, 200);

02

varc
= paper.ellipse(100, 100, 10, 10);

03

c.attr({

04

'fill':'#00aeef',

05

'stroke':'#00aeef'

06

});

07

08

varr
= paper.rect(60, 60, 80, 80);

09

r.attr({

10

'stroke-width':
2,

11

'stroke':'#00aeef'

12

});

13

14

setInterval(function()
{

15

r.rotate(6);

16

},
33);

Raphaël is similar to Paper.js in its object-oriented approach. We have a square, and we call a rotatefunction
on it. Thus, we can easily spin the square with a small amount of code.

Interaction

Raphaël shines when you need to enable interactivity in a drawing. It provides an event model similar to JavaScript’s, making it easy to detect clicks, drags and touches. Let’s make our square clickable.