
Getting Started With Paper.js: Paths and Geometry
Wednesday, October 12, 2016 by martijn broeders
In my previous tutorial, I covered the installation process and project hierarchy in Paper.js. This time I will teach you about paths, segments, and their manipulation. This will enable you to create complex shapes using the library. After that, I would like to cover a few basic geometric principles that Paper.js is based on.
Working With Paths
Paths in Paper.js are represented by a sequence of segments that are connected by curves. A segment is basically a
point
and its two handles, which define the location and direction of the curves. Not defining segment handles results in straight lines instead of curves.Once you define a new path using the
new Path()
constructor, you can add segments to it with the help of thepath.add(segment)
function. As this function supports multiple arguments, you can also add many segments at once. Let's say you want to insert a new segment at a specific index inside an existing path. You can do so by using thepath.insert(index, segment)
function. Similarly, to remove a segment at a specific index, you can use thepath.removeSegment(index)
function. Both these functions use zerobased indexing. This implies that usingpath.removeSegment(3)
will remove the fourth segment. You can close all the paths you draw with thepath.closed
property. It will join the first and last segments of the path together.Till now all our paths had straight lines. To create curved paths without specifying handles for each segment, you can use the
path.smooth()
function. This function calculates the optimal values for handles of all the segments in a path in such a way that the curve that goes through them is smooth. The segments themselves don't change their location, and if you have specified handle values for any of the segments, those values will be ignored. The code below uses all the functions and properties we discussed to create four paths, two of which are curved.var aPath = new Path(); aPath.add(new Point(30, 60)); aPath.add(new Point(100, 200)); aPath.add(new Point(300, 280), new Point(280, 40)); aPath.insert(3, new Point(180, 110)); aPath.fullySelected = 'true'; aPath.closed = true; var bPath = aPath.clone(); bPath.smooth(); bPath.position.x += 400; var cPath = aPath.clone(); cPath.position.y += 350; cPath.removeSegment(3); var dPath = bPath.clone(); dPath.strokeColor = 'green'; dPath.position.y += 350; dPath.removeSegment(3);
First, we create a new path and then add segments to it. Using
path.insert(3, new Point(180, 110))
inserts a new segment in place of the fourth one and moves the fourth segment to the fifth position. I have setfullySelected
totrue
to show you all points and handles for each curve. For the second path, I have used thepath.smooth()
function to make the curve smooth. Removing the fourth segment usingcPath.removeSegment(3)
gives us our original shape without any indexbased insertions. You can verify this by commenting outaPath.insert(3, new Point(180, 110));
in this CodePen demo. This is the final result of all our manipulations up to this point:Predefined Shapes
Paper.js supports some basic shapes out of the box. For instance, to create a circle, you can simply use the
new Path.Circle(center, radius)
constructor. Similarly, you can use thenew Path.Rectangle(rect)
constructor to create a rectangle. You can either specify the topleft and bottomright corners or specify the topleft corner and the size of the rectangle. To draw a rectangle with rounded corners, you can use thenew Path.RoundedRectangle(rect, size)
constructor where the size parameter determines the size of rounded corners.If you want to create an nsided regular polygon, you can do so by using the
new Path.RegularPolygon(center, numSides, radius)
constructor. The parametercenter
determines the center of our polygon, and radius determines the radius of our polygon.The code below will generate all the shapes that we just discussed.
var aCircle = new Path.Circle(new Point(75, 75), 60); aCircle.strokeColor = 'black'; var aRectangle = new Path.Rectangle(new Point(200, 15), new Point(400, 135)); aRectangle.strokeColor = 'orange'; var bRectangle = new Path.Rectangle(new Point(80, 215), new Size(400, 135)); bRectangle.strokeColor = 'blue'; var myRectangle = new Rectangle(new Point(450, 30), new Point(720, 170)); var cornerSize = new Size(10, 60); var cRectangle = new Path.RoundRectangle(myRectangle, cornerSize); cRectangle.fillColor = 'lightgreen'; var aTriangle = new Path.RegularPolygon(new Point(120, 500), 3, 110); aTriangle.fillColor = '#FFDDBB'; aTriangle.selected = true; var aDodecagon = new Path.RegularPolygon(new Point(460, 490), 12, 100); aDodecagon.fillColor = '#CCAAFC'; aDodecagon.selected = true;
The first rectangle that we create is based on coordinate points. The next one uses the first point to determine the topleft corner of our rectangle and then uses the size value to plot the rest of the points. In the third rectangle, we have additionally specified a radius for our rectangle. The first radius parameter decides the horizontal curvature, and the second parameter determines the vertical curvature.
The last two shapes just use the
RegularPolygon
constructor to create a triangle and a dodecagon. The embedded demo below shows the result of our code.Simplifying and Flattening Paths
There are two ways to create a circle. The first one is to create a lot of segments without any handles and place them closely together. This way, even though they will be connected by a straight line, the overall shape will still be closer to a circle. The second way is to use just four segments with appropriate values for their handles. This can save a lot of memory and still give us the desired results.
Most of the time we can remove quite a few segments from a path without significant changes in its shape. The library provides a simple
path.simplify([tolerance])
function to achieve this result. The tolerance parameter is optional. It is used to specify the maximum distance to which the pathsimplifying algorithm can deviate from its original path. It is set to 2.5 by default. If you set the parameter to a higher value, the final curve will be a bit smoother, with fewer segment points, but the deviation could be significant. Similarly, a lower value will result in very little deviation but include many more segments.You can also convert the curves in a path to straight lines using the
path.flatten(maxDistance)
function. While flattening a path, the library tries to keep the distance between segments as close tomaxDistance
as possible.var aPolygon = new Path.RegularPolygon(new Point(140, 140), 800, 120); aPolygon.fillColor = '#CCAAFC'; aPolygon.selected = true; var bPolygon = aPolygon.clone(); bPolygon.fillColor = '#CCFCAA'; bPolygon.simplify(); var cPolygon = aPolygon.clone(); cPolygon.fillColor = '#FCAACC'; cPolygon.simplify(4); var dPolygon = bPolygon.clone(); dPolygon.fillColor = '#FCCCAA'; dPolygon.flatten(80);
In the code above, I first created a polygon using the
RegularPolygon
function discussed above. I have intentionally set theselected
property totrue
so that all the segments from these paths are visible. Then I cloned the second polygon from the first one and used thesimplify
function on it. This reduced the number of segments to just five.In the third polygon, I have set the tolerance parameter to a higher value. This further reduces the number of segments. You can see that all the paths still have the same basic shape. In the final path, I have used the
flatten(maxDistance)
function to flatten our curve. The algorithm tries to keep the shape as close to the original one as possible while still respecting themaxDistance
constraint. Here is the final result:Geometry and Mathematics
Paper.js has some basic data types like
Point
,Size
, andRectangle
to describe geometric attributes of graphical items. They are abstract representations of geometric values like location or dimension. A point just describes a twodimensional location, and size describes abstract dimensions in twodimensional space. The rectangle here signifies an area enclosed by the topleft point, its width and its height. It is different from the rectangular path that we discussed earlier. Unlike the path, it is not an item. You can read more about them all in this Paper.js tutorial.You can perform basic mathematical operations—addition, subtraction, multiplication, and division—on points and sizes. All the operations below are valid:
var pointA = new Point(20, 10); var pointB = pointA * 3; // { x: 60, y: 30 } var pointC = pointB  pointA; // { x: 40, y: 20 } var pointD = pointC + 30; // { x: 70, y: 50 } var pointE = pointD / 5; // { x: 14, y: 10 } var pointF = pointE * new Point(3, 2); // { x: 42, y: 20 } // You can check the output in console for verification console.log(pointF);
Besides these basic operations, you can also perform some rounding operations or generate random values for points and sizes. Consider the following examples:
var point = new Point(3.2, 4.7); var rounded = point.round(); // { x: 3, y: 5 } var ceiled = point.ceil(); // { x: 4, y: 5 } var floored = point.floor(); // { x: 3, y: 4 } // Generate a random point with x between 0 and 50 // and y between 0 and 40 var pointR = new Point(50, 40) * Point.random(); // Generate a random size with width between 0 and 50 // and height between 0 and 40 var sizeR = new Size(50, 40) * Size.random();
The
random()
function generates random values between 0 and 1. You can multiply them with aPoint
orSize
object of appropriate value to get the desired results.This concludes the basic mathematics that you need to be familiar with to create something useful with Paper.js.
Final Thoughts
After following this tutorial, you should be able to create a variety of paths and shapes, flatten curves, or simplify complex paths. Now you also have a basic understanding of various mathematical operations that you can perform with Paper.js. By combining all that you have learnt in this and the previous tutorial of the series, you should be able to create complex polygons on different layers and blend them together. You should also be able to insert and remove segments from a path to get a desired shape.
If you’re looking for additional JavaScript resources to study or to use in your work, check out what we have available in the Envato marketplace.
If you have any questions regarding this tutorial, please let me know in the comments.
Leave a comment › Posted in: Daily
0 Comments