Composition

Grade 6~8

A. Symmetry and Asymmetry

Symmetry and asymmetry

In composition, symmetry and asymmetry are equally valuable techniques to achieve visual rhythm and harmony.

In the following tutorial, we will use the lollipop sketch as the starting point to draw a wild flower on the sidewalk. The wild flower is going to contain both symmetrical and asymmetrical visual elements.

Symmetrical cloud sketch

First, let’s turn the lollipop stick into a stem just by adjusting the fill() and the rect():

  //Stem
  fill(22, 102, 36);
  rect(200, 300, 6, 150);

Then, let’s turn the lollipop candy into a pistil by adding another ellipse():

  //Pistil
  fill(189, 123, 30);
  ellipse(200, 200, 50, 50);
  
  fill(43, 26, 1);
  ellipse(200, 200, 35, 35);

We’ll also add a sidewalk for the flower to sit on:

  //Ground
  fill(120, 130, 127);
  rect(200, 365, 400, 75);

Symmetrical cloud sketch

Let’s add two petals to the flower. The petals will stand behind the left and right side of the pistil:

  //Petals
  fill(230, 196, 28);
  ellipse(200 + 30, 200, 50, 40); // offset petal 30 pixel to the right
  ellipse(200 - 30, 200, 50, 40); // offset petal 30 pixel to the left

Using arithmetic operators such as addition (+) and subtraction (-) allow us to offset one petal 30 pixel to the left, and the other petal 30 pixel to the right, making it easier to create symmetrical drawings.

Symmetrical cloud sketch

To add two more petals to the flower, one on the top and one on the bottom of the pistil, we will have to manipulate the Y positions of the ellipses:

  //Petals
  fill(230, 196, 28);
  ellipse(200 + 30, 200, 50, 40); // offset petal 30 pixel to the right
  ellipse(200 - 30, 200, 50, 40); // offset petal 30 pixel to the left
  ellipse(200, 200 + 30, 40, 50); // offset petal 30 pixel to the bottom
  ellipse(200, 200 - 30, 40, 50); // offset petal 30 pixel to the top

Symmetrical cloud sketch

Voila! Now we have a symmetrical flower with petals perfectly offset from the center of the pistil.

Let’s complete this image by adding leaves:

   //Stem and leaves
  fill(22, 102, 36);
  rect(200, 300, 6, 150);
  
  ellipse(200 + 25, 200 + 70, 50, 20); // offset leaf 25 pixel to the right, and 70 pixel to the bottom
  ellipse(200 - 25, 200 + 90, 50, 20); // offset leaf 25 pixel to the left, and 90 pixel to the bottom

While the leaves are symmetrical on the X-axis, they are asymmetrical on the Y-axis, creating a cascading effect.

Code Snippet: flower example.

Grade 9~12

B. Grouped Drawing

As your p5.js journey unfold, you might find yourself wanting to move or resize a group of shapes all at the same time. This is achievable through features listed under the Transform category.

To begin, let’s draw a cloud using the translate() feature:

Symmetrical cloud sketch

By default, the p5.js canvas origin (0, 0) is at the sketch’s top-left corner. translate() shifts the canvas origin to a different position.

function setup() {
  createCanvas(400, 400);
  rectMode(CENTER);
  noStroke();
}

function draw() {
  background(122, 122, 190);
  fill(255);
  
  // Shifts canvas origin to the center of the canvas
  translate(400 / 2, 400 / 2); // x, y

  // The rectangle refers to the new canvas origin to determine X, Y positions
  rect(0, 0, 100, 50);
}

Symmetrical cloud sketch

Now we’ll add a bunch of ellipses after the rectangle to create the cloud shape:

  ellipse(-80, 0, 70, 70); // offset ellipse 80 pixel to the left
  ellipse(80, 0, 70, 70); // offset ellipse 80 pixel to the right

Symmetrical cloud sketch

  ellipse(-40, -40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the top
  ellipse(40, 40, 70, 70);  // offset ellipse 40 pixel to the right, and 40 pixel to the bottom
  ellipse(-40, 40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the bottom
  ellipse(40, -40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the top

Symmetrical cloud sketch

  ellipse(0, -50, 70, 70); // offset ellipse 50 pixel to the top
  ellipse(0, 50, 70, 70); // offset ellipse 50 pixel to the bottom

Symmetrical cloud sketch

Great work! Before moving on to draw another shape, make sure that you sort your cloud drawing into a group using push() and pop().

Code Snippet: cloud example.

From this point on, you can draw a new shape, or copy and paste the cloud drawing into a new position on the canvas by manipulating the translate() values:

function setup() {
  createCanvas(400, 400);
  rectMode(CENTER);
  noStroke();
}

function draw() {
  background(122, 122, 190);
  fill(255);

  // Cloud 1

  // Begin tranformation
  push();

  // Shifts canvas origin to a new location
  translate(60, 60); // x, y
  
  // The rectangle refers to the new canvas origin to determine X, Y positions
  rect(0, 0, 100, 50);

  ellipse(-80, 0, 70, 70); // offset ellipse 80 pixel to the left
  ellipse(80, 0, 70, 70); // offset ellipse 80 pixel to the right

  ellipse(-40, -40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the top
  ellipse(40, 40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the bottom
  ellipse(-40, 40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the bottom
  ellipse(40, -40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the top

  ellipse(0, -50, 70, 70); // offset ellipse 50 pixel to the top
  ellipse(0, 50, 70, 70); // offset ellipse 50 pixel to the bottom

  // End transformation
  pop();

  // Cloud 2

  // Begin tranformation
  push();

  // Shifts canvas origin to a new location
  translate(200, 200); // x, y
  
  // The rectangle refers to the new canvas origin to determine X, Y positions
  rect(0, 0, 100, 50);

  ellipse(-80, 0, 70, 70); // offset ellipse 80 pixel to the left
  ellipse(80, 0, 70, 70); // offset ellipse 80 pixel to the right

  ellipse(-40, -40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the top
  ellipse(40, 40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the bottom
  ellipse(-40, 40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the bottom
  ellipse(40, -40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the top

  ellipse(0, -50, 70, 70); // offset ellipse 50 pixel to the top
  ellipse(0, 50, 70, 70); // offset ellipse 50 pixel to the bottom

  // End transformation
  pop();

  // Cloud 3

  // Begin tranformation
  push();

  // Shifts canvas origin to a new location
  translate(350, 350); // x, y
  
  // The rectangle refers to the new canvas origin to determine X, Y positions
  rect(0, 0, 100, 50);

  ellipse(-80, 0, 70, 70); // offset ellipse 80 pixel to the left
  ellipse(80, 0, 70, 70); // offset ellipse 80 pixel to the right

  ellipse(-40, -40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the top
  ellipse(40, 40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the bottom
  ellipse(-40, 40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the bottom
  ellipse(40, -40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the top

  ellipse(0, -50, 70, 70); // offset ellipse 50 pixel to the top
  ellipse(0, 50, 70, 70); // offset ellipse 50 pixel to the bottom

  // End transformation
  pop();
}

Symmetrical cloud sketch

C. Illusion of Depth

scale() is a p5.js feature that makes it possible to resize the things we drew:

  // Begin tranformation
  push();

  // Shifts canvas origin to the center of the canvas
  translate(400 / 2, 400 / 2); // x, y
  
  scale(0.5); // Shrink the drawing to 50% of its original size

  // The rectangle refers to the new canvas origin to determine X, Y positions
  rect(0, 0, 100, 50);

  ellipse(-80, 0, 70, 70); // offset ellipse 80 pixel to the left
  ellipse(80, 0, 70, 70); // offset ellipse 80 pixel to the right

  ellipse(-40, -40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the top
  ellipse(40, 40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the bottom
  ellipse(-40, 40, 70, 70); // offset ellipse 40 pixel to the left, and 40 pixel to the bottom
  ellipse(40, -40, 70, 70); // offset ellipse 40 pixel to the right, and 40 pixel to the top

  ellipse(0, -50, 70, 70); // offset ellipse 50 pixel to the top
  ellipse(0, 50, 70, 70); // offset ellipse 50 pixel to the bottom

  // End transformation
  pop();

Symmetrical cloud sketch

Code Snippet: shrunk cloud example.

Combining translate(), scale(), push() and pop() opens up enormous potentials for creating illusion of depth.

Play around with the multiple clouds example by resizing each cloud. Are you able to use scale() to make a cloud appear closer or further away?

Symmetrical cloud sketch

Code Snippet: multiple clouds with depth example.