Centering Things with P5JS

P5JS is an incredible visualization library. No matter how crisp your design is in your imagination you'll surely want to have it centered on your canvas! This short tutorial will show you how to leverage the power of P5JS to do just that!
p5js centering alpharithms

The P5JS library is an excellent port of the infamous Java-based Processing library. Each is used for visual designs and is the go-to tool for many generative artists. The P5JS library approaches the centering of objects a bit strange and this approach can throw beginners for a loop.

P5JS has a lot of built-in functions that are somewhat magic when first starting. Functions like fill(), stroke(), no fill(), background() can affect different things depending on when they are called. This functional design can take some getting used to—especially when it comes to translating, rotating, and orienting objects.

Note: You can follow along with the code in this post via the online P5JS Editor.

Setting up the Scene

P5JS abstracts away a lot of the lower-level requirements for visualizations. As such, setting up a new scene is quite easy. There are two basic functions to be aware of: setup and draw. The setup() function gets called during initialization and is called continuously throughout the script. Let’s set our scene up as follows:

// Some variables for convenience (optional)
const height = 512
const width = 512

/**
 * Gets called during scene initialization
 */
function setup(){
    createCanvas(width, height)
    background("#efefef")
}

/**
 * Called continuously during visualization
 */
function draw(){
    // We will add code here
}

This results in a “blank” scene with only our canvas object showing:

p5js canvas
A blank canvas of 512px x 512px in dimensions created by the setup() function

During the creation of this canvas object, the following elements and data are added to the HTML file having loaded this script (index.html in the case of this test.)

<main>
    <canvas id="defaultCanvas0" class="p5Canvas" width="512" height="512" style="width: 512px; height: 512px;"></canvas>
</main>

P5JS allows the addition of classes, specification of which element to add the code to, and a whole mess of other useful functions. For our discussion here, however, we’ll be focused only on placing and aligning objects onto the canvas. As the saying goes—best to start at the beginning. Or, in the case of P5JS—the top.

Starting at the Top

The P5JS canvas is indexed as a pixel grid coordinate system that ranges from 0-width in width and 0-height in height. In the case of our example here, both the height and width values have been defined as 512px. Let’s see what happens when we add a shape to our scene in the draw() function:

rect(0, 0, 64, 64);

This creates a rectangle shape at the coordinates (0, 0) with a width and height of 64. For more details on how to create a rectangle, check out the official P5JS documentation. There are tons of fun ways in which one can alter rectangles by preference. The image below reflects our canvas with the newly-minted rect object:

p5js add rect
The default rectangle shape has a fill color of white and a stroke color of black.

P5JS will add an object to the coordinates (0, 0) by default—as opposed to nicely centering things in the middle of our canvas. This seemed like an annoyance to me when first getting familiar with this library. However, it becomes second nature to reposition things once one gets used to the P5JS workflow.

Finding the Center

P5JS makes translations and rotations simple via built-in methods. To get our rectangle shape to the center of the canvas requires little more than a single call to the P5JS translate function as such:

/**
 * Called continuously during visualization
 */
function draw(){

    // Affects all objects after this call
    translate(width / 2, height / 2);

    rect(0, 0, 64, 64)
    
}

This instructs P5JS to move out rectangle by on the x-axis by a [positive] value of width / 2 and on the y-axis by a [positive] value of height / 2. Keeping in mind our global constants from earlier, we know these values result in 256-pixel translations (512 / 2 = 256.) This results in the following image:

p5JS translate rectangle function
The translate function moves our rectangle along the x and y-axis by the specified values.

This is getting close to having our rectangle centered but notice that it seems a little off-center—albeit much better overall! This is due to P5JS’s default indexing of the rectangle’s values starting with the top-leftmost pixel (the same approach as with the canvas.)

Finding the Center, Again

This re-iterated topmost approach to indexing means our rectangle is off-center by +(width / 2) and +(height / 2) along the x and y axis, respectively. There are at least two approaches for addressing this, with one being much more elegant. Let’s start with the annoying approach first:

// Subtract half of our shape's dimension from
// from each axis dimension. 
translate(width / 2 - 32, height / 2 - 32);

Here we are simply decrementing the amount of our translation by half of our rectangle’s value in both the x and y-axis directions. This stops our translation short, resulting in the center of our rectangle aligning with the center of the canvas.

This accomplishes our goal but means we will probably need to manage another variable (for the shape size). If we start creating actual rectangles (and not squares) that will mean juggling two variables—one for shapeHeight and shapeWidth. Fortunately, P5JS has a built-in method to ease our burden: rectMode().

The recMode() function can accept several arguments depending on how one chooses to approach. For centering, the two most relevant arguments are CENTER and RADIUS.

The CENTER argument creates a rectangle from the center out as does the RADIUS method. However, the RADIUS parameter specifies the rectangle to be created where the width and height are half of the resulting width (like creating a circle). Let’s add this to our code using the following:

/**
 * Called continuously during visualization
 */
function draw(){
    // Aligns the rectangle from the center
    // rather than the top-left corner
    rectMode(CENTER)
    translate(width / 2, height / 2);
    rect(0, 0, 64, 64)

}

This results in the following image:

P5JS rectMode function center
The rectMode(CENTER) function aligns the center of the rectangle to the coordinates specified in our following translate() function.

This approach reflects the ease by which P5JS allows artists to focus on design rather than underlying implementation details. This contrasts other more technical libraries like vanilla JS, Three.js or other common visualization libraries. This is all one needs to know to center things easily—but let’s take a quick look at how to make our rectangle look a bit more appealing as well!

All Things Nice

Now that we have centered our rectangle let’s add a few aesthetic details before we wrap things up. Being a visualization library, P5JS has an immense number of functions and utilities for creativity. Here we’ll stick to the default parameters of the rect object and add a fill color, increase the size a bit, and add a radius on all the corners:

/**
 * Called continuously during visualization
 */
function draw(){

    // Center the rectangle, color, and remove stroke
    rectMode(CENTER)
    translate(width / 2, height / 2);
    fill("#ff9900")
    noStroke()


    // Create the rectangle
    rect(0, 0, 128, 128, 32)

}

Given the functional nature of P5JS, it’s important to note the order in which we make these specifications are important. Note that all the fiddling about with our rectangle here—the centering, repositioning, fill color, and removal of the stroke—all happen before the call to the rect() function. This results in the following image:

p5js centered rectangle alpharithms
P5JS offers ease in updating visual attributes like border-radius, fill color, size, and position.

Final Thoughts

P5JS is one of the most popular libraries for generative art and comes packed with high-level visualization APIs. While firmly focused on 2D visualizations this library is still packed with lots of 3D capabilities. It’s not designed to be a gaming engine like other visualization libraries such as Three.js—but that’s on purpose!

The simplicity by which we have seen a canvas object, rectangle, and resulting placement created to attest to this library’s power. Whether you are randomly placing thousands of rectangles or creating complex algorithmic visualizations—P5JS can help fuel your creativity.

 

Zαck West
Full-Stack Software Engineer with 10+ years of experience. Expertise in developing distributed systems, implementing object-oriented models with a focus on semantic clarity, driving development with TDD, enhancing interfaces through thoughtful visual design, and developing deep learning agents.