Advertisement
  1. Code
  2. JavaScript

Getting Started With Paper.js: Animation and Images

Scroll to top
6 min read
This post is part of a series called Getting Started With Paper.js.
Getting Started With Paper.js: User Interaction

So far in this series, I have covered projects and items, paths and geometry, and user interaction in Paper.js. The library also allows you to animate various items in your projects. If you combine it with the ability to act based on user input, you can create some really cool effects. This tutorial will cover how to animate items in Paper.js.

Later sections of the tutorial will also cover image manipulation and how you can manipulate the colors of individual pixels. The library also enables you to create rasters from vectors which will be covered in the end.

Animation Basics

All the animations in Paper.js are handled by the onFrame event handler. The code inside the handler is executed up to 60 times per second. The view is redrawn automatically after every execution. Gradually changing some properties inside the function can create some really nice effects.

The onFrame handler function also receives an event object. The object has three properties which provide us with information relevant to the animation. 

The first one is event.count, which tells us the number of times that the handler is executed. The second one is event.delta, which gives us the total amount of time that has passed since the last execution of our handler. The third one is event.time, which gives us the time that has passed since the first frame event.

You can animate a lot of properties inside the handler. In our example, I will rotate three rectangles and change the hue of the central rectangle. Consider the code below:

1
var rectA = new Path.Rectangle({
2
  point: [300, 100],
3
  size: [200, 150],
4
  strokeColor: 'yellow',
5
  strokeWidth: 10
6
});
7
8
var rectB = rectA.clone();
9
rectB.strokeColor = 'orange';
10
rectB.scale(0.8);
11
var rectC = rectA.clone();
12
rectC.strokeColor = 'black';
13
rectC.scale(1.2);
14
15
function onFrame(event) {
16
  rectA.strokeColor.hue += 10 * event.delta;
17
  rectA.rotate(2);
18
  rectB.rotate(2);
19
  rectC.rotate(2);
20
}

As apparent from the snippet above, the actual code needed to animate our rectangles is pretty minimal. For rectangle A, we increment the hue by 10 times event.delta on each execution of the onFrame handler. The value of event.delta will generally be close to 0.01. If I had not multiplied its value by 10, it would have taken a long time to notice the change in color. 

I am also rotating each rectangle by 2 degrees every time the code is executed. If we were to use the value event.time to rotate the rectangles, the rotations would have become very fast after some time.

Instead of animating the whole path or item at once, you can also animate individual segments. The process itself is pretty simple. You can use path.segments to return an array of all segments constituting a path. Individual segments can be accessed by supplying an index value. Before going further, I would like you to take a look at the code below.

1
var aSquare = new Path.RegularPolygon(new Point(550, 200), 4, 100);
2
aSquare.fillColor = 'pink';
3
aSquare.fullySelected = true;
4
5
function onFrame(event) {
6
  for (var i = 0; i <= 3; i++) {
7
    var sinValue = Math.sin(event.time * 4 + i);
8
    
9
    aSquare.segments[i].point.x = sinValue * 100 + 350;
10
  }
11
  aSquare.segments[1].point.y = sinValue * 50 + 100;
12
}

Here, we begin by creating a square using the Path.RegularPolygon(center, sides, radius) constructor. The sides parameter determines the number of sides of our polygon. The radius parameter determines the size of our polygon. I have also set the fullySelected property to true so that you can see the individual points.

Inside the onFrame handler, I iterate over all the segments using a for loop and set their x-coordinate equal to a value calculated based on their index. Using event.time inside the Math.sin() function does not create any issues related to extreme values because the value of the Math.sin() function will always lie between -1 and 1. 

The following demo shows our animated square, which by the way is no longer a square, thanks to the code inside our onFrame handler. I would like to suggest that you try out different values for the parameters of our polygon constructor as well as the sin function to see how they affect the final animation in the demo.

Image Basics

Images in Paper.js are referred to as Rasters. You can transform and move them around like any other item. To use an image in your project, you will first have to add it to the markup of your web page using the usual img tag and give it an id. This id is later passed to the new Raster(id) constructor.

Keep in mind that the images you are working with need to be already loaded and should be hosted on the same website as your project. Using images hosted on other domains will result in security errors. In this tutorial we will be manipulating the following image:

Sample image of robots and sunsetSample image of robots and sunsetSample image of robots and sunset

To access the colors of individual pixels in the image above, you can use the raster.getPixel(x, y) function, where x and y are the co-ordinates of our pixel. The code below generates 7*7 pixel squares filled with the color of pixels located at their top left corner:

1
var raster = new Raster('landscape');
2
var gridSize = 8;
3
var rectSize = 7;
4
5
raster.on('load', function() {  
6
  raster.size = new Size(80, 40);
7
8
  for (var y = 0; y < raster.height; y++) {
9
    for (var x = 0; x < raster.width; x++) {
10
      
11
      var color = raster.getPixel(x, y);
12
      var path = new Path.Rectangle( new Point(x, y) * gridSize, new Size(rectSize, rectSize));
13
14
      path.fillColor = color;
15
    }
16
  }
17
18
  project.activeLayer.position = view.center;
19
});

After the raster has loaded, we resize it to 80*40. pixels. Inside the nested for loops, we go over individual pixels of this raster and create 7*7 squares. Increasing the size of our raster will give us better results, but the execution would be slower. Here is the final result with the resized raster visible in the top left corner:

If you want to hide the resized raster, you can set the raster.visible property to false. You can also manipulate the color of generated squares. For instance, to increase the red component in all the squares, you can use the following line:

1
path.fillColor = color + new Color(0.4,0,0);

The final result, in this case, would be:

Rasterizing Items

While Paper.js is a vector graphics library, it also allows you to create rasters from existing items. To do so, you will have to use the item.rasterize() method. The original item itself is not removed from the project after rasterization. You can also optionally specify the resolution of your raster in pixels per inch. The code below creates two rasters from a polygon at different resolutions:

1
var aDodecagon = new Path.RegularPolygon(new Point(150, 180), 12, 30);
2
aDodecagon.fillColor = '#CCAAFC';
3
  
4
var dodecRasterA = aDodecagon.rasterize();
5
dodecRasterA.position.x += 250;
6
  
7
var dodecRasterB = aDodecagon.rasterize(150);
8
dodecRasterB.position.x += 500;
9
  
10
aDodecagon.scale(3);
11
dodecRasterA.scale(3);
12
dodecRasterB.scale(3);

The rightmost polygon with higher resolution is still sharp compared to the middle one. Here is the final result:

Final Thoughts

If you have followed all the tutorials in this series, you should have enough knowledge to get started with Paper.js. While it is easy to learn the basics of the library, mastering all the concepts will require some effort on your part. Whenever you need more information about a topic, you can go through the reference on the official website. 

JavaScript has become one of the de facto languages of working on the web. It’s not without its learning curves, and there are plenty of frameworks and libraries to keep you busy, as well. If you’re looking for additional resources to study or to use in your work, check out what we have available in the Envato marketplace.

If you create something interesting using this library, please share your work in the comments. 

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.