Shown below is my self-portrait coded with p5.js. The link to the code online can be found here.



For this piece, I was inspired by the human face sketches that we are commonly taught in beginner art classes that are meant to teach us proportions/anatomy/ratios. The sketch is realistic in this sense, but it also purposefully lacks detail when it comes to the eyes, ears, and nose for example. The portrait has been drawn exclusively black and white, and the features consist of several of the same shape layered on top of each other. All of these aspects I chose intentionally to mimic real pencil strokes and the process of re-outlining and re-tracing that happens when sketching on paper. Finally, the sketch is dynamic in that the face shifts slightly and the eyes blink according to the frame count. This was a feature that was later added on because it reminded me of primitive 2D animations.



The code itself is not particularly complex; I made separate functions to draw each of the features: face shape, eyebrows, eyes, nose, ears, and mouth. A method I found particularly helpful for this project was curveVertex(); I used this to create custom shapes for the chin, ears, and mouth. The eyes, eyebrows, and nose were drawn using simple lines and arcs. The “sketch” effect is created by layering shapes/line of different sizes and positions 6 times using a for loop, as shown in the code snippet below:

for (let i=0; i<=6; i++) {
  x = random(-8, 8); 
  y = random(-8, 8);
  b = random(-8, 8); 
  draw_face(x, y, b);
  draw_ears(x, y, b);

The variation of shapes is determined by variables x, y, and b that are passed through the functions draw_face(), draw_ears(), etc. The x and y variables were used mainly to shift the overall position of a shape, as it was used in the translate() function, and b was used as an additional variable to manipulate proportions such as an arc’s width or a line’s length or intensity of a curve.  For example, in the draw_ears, the x and y variables manipulate the position of  the ears on the canvas.

function draw_ears(x, y) { 
  translate(x, y); 

  curveVertex(140, -10);

In the case of the eyebrows, b is used to draw eyebrows of varying “arched-ness”.

function draw_eyebrow(x, y, b) { 
  translate(x, y); 
  arc(-90, 0, 90+b, 12+b, 180, 360); 

The lines that bisect the center of the face, the mouth, and eyebrows were created in a separate for loop that executed only 4 times and calculated random x, y and b values from a smaller range (see below). The decision behind making a second for loop was for visual purposes only.

for (let i=0; i<=5; i++) {
  x = random(-3, 3); 
  y = random(-3, 3);
  buffer = random(-6, 6);
  draw_eyebrow(x, y, b); 
  // draw_mouth(x, y);
  draw_mouth(x, y, b); 
  draw_outlines(x, y); 


Using the two loops and the randomized variables allowed every line, curve, and shape on the face to be drawn differently with each frame, giving the face its movement.  While p5.js’ standard frame rate is 60, I also altered the frame rate to be slower so that the sketch would look like real hand drawn animation. Contrarily, I played around using randomSeed() to create a still image, but in the end I prefer the dynamic one.

My favorite feature of this sketch are the blinking eyes. This was achieved by having two functions draw_eyes() and draw_eyes_closed, which were called upon depending on an if block in the for loop:

if (frameCount%6==0) { 
else { 

In short, the if statement inside the for loop executes every 6 frames and calls draw_eyes_closed(); the shape of a closed eye was simply the bottom half of the parallelogram that is the open eye. Otherwise, draw_eyes() is called and thus shows its eyes open.


Overall I am happy with this first sketch; I think I was able to explore my creativity and create something that was uniquely my style. Personally I do not enjoy drawing myself, but I think choosing this style allowed me to not be so focused on details and instead accentuate features on myself that I like, such as the eye shape and mouth. I challenged myself by making the sketch dynamic and including the blinking feature. One thing I wish I could have included is eyelashes and pupils that moved with each blink, and I would love to try to expand the sketch to a full body self-portrait.

One thought on “Self-Portrait”

Leave a Reply