DEV Community

Cover image for When Pendulum Physics Becomes Art: Implementing a Pollock-Style Generative Art Generator
usapop
usapop

Posted on

When Pendulum Physics Becomes Art: Implementing a Pollock-Style Generative Art Generator

Clicking the Paint button generates a different pattern each time.
The embed above may be cropped, so I'd recommend opening it in a larger window on CodePen: https://codepen.io/kokoyoshi/pen/YPWVwPB

Example output from the generator

Introduction

Are you familiar with Jackson Pollock?

He's the painter known for laying canvases on the floor and dripping paint from above. This technique, called "drip painting," made him one of the most representative American artists of the 20th century (here are some examples of his work).

At first glance, it might look like he was just randomly splattering paint. But actually, Pollock sometimes painted by swinging a paint-filled container on a string like a pendulum. Since it's a pendulum, it follows the laws of physics—slowing down at the edges where paint accumulates, speeding up in the center where it stretches thin.

What's even more interesting is that according to a 1999 study published in Nature by physicist Richard Taylor, the patterns created by this technique turned out to be fractals—the self-similar structures found throughout nature. And there's also research suggesting that viewing these fractals can reduce human stress by 60%.

Pendulum physics → Fractals → A sense of calm.

I found this chain fascinating and decided to try recreating it in code. This implementation is just one possible approach, so please consider it as a reference.

Breaking Down the Physics

Let me organize the visual characteristics that emerge from pendulum motion.

Physical Phenomenon Visual Characteristic
Slowing at pendulum edges Lines become thick and dense (paint accumulates)
Accelerating at center Lines become thin and faint (paint stretches)
Centrifugal force Paint splatters fly off
Multiple swings Trajectories overlap
Repeating with multiple colors Layered appearance

I'll recreate these in code.

Implementation: Pendulum Trajectories

Basic Movement

First, let's recreate the pendulum's velocity changes.

const speed = baseSpeed * (0.3 + Math.abs(Math.sin(phase)) * 0.7);
Enter fullscreen mode Exit fullscreen mode

Using sin(phase) creates the acceleration and deceleration. Slow at the edges (sin=0), fast at the center (sin=1). This is essentially the pendulum's equation of motion.

From Velocity to Thickness and Opacity

Once velocity is calculated, I convert it to visual attributes.

// Slower = thicker
const curve = Math.pow(1 - normalizedVelocity, 1.5);
thickness = lerp(minThickness, maxThickness, curve);

// Slower = more opaque
opacity = lerp(0.05, 1.0, 1 - normalizedVelocity);
Enter fullscreen mode Exit fullscreen mode

I'm using a non-linear curve (power of 1.5) because linear mapping didn't seem to produce enough contrast. This was adjusted by eye.

Boundary Reflection

Pendulums change direction at their endpoints. When the position exceeds the canvas boundary, I have it return toward the center.

if (isOutsideBounds(x, y)) {
  // Calculate angle toward center
  const toCenter = Math.atan2(centerY - y, centerX - x);
  // Add some randomness for the new direction
  moveAngle = toCenter + randomRange(-0.25, 0.25) * Math.PI;
}
Enter fullscreen mode Exit fullscreen mode

The key point is that instead of bouncing within the canvas, it goes outside and then comes back. This creates strokes that sweep from edge to edge.

Drips

The strokes alone felt a bit lacking to me, so I added paint splatters. They represent paint flying off due to the pendulum's momentum. They're generated probabilistically and drawn as shrinking circles along the velocity vector.

// Probabilistically generate drips
if (Math.random() < 0.002 && isInsideCanvas(x, y)) {
  drips.push(createDrip(x, y));
}

// Draw drips: continuously draw shrinking circles
while (radius > 0.5) {
  drawCircle(x, y, radius);
  x += vx * 0.1;
  y += vy * 0.1;
  radius *= 0.85;
}
Enter fullscreen mode Exit fullscreen mode

Layering Colors

Pollock painted with multiple overlapping colors. He seems to have commonly used black, red, blue, yellow, and white.

const layers = [
  { color: '#1a1a1a' },  // Black
  { color: '#c0392b' },  // Red
  { color: '#6e3b1a' },  // Burnt umber
  { color: '#2980b9' },  // Blue
  { color: '#f1c40f' },  // Yellow
  { color: '#ffffff' },  // White
];
Enter fullscreen mode Exit fullscreen mode

I'm using mix-blend-mode: darken here. This blend mode lets darker colors dominate, which creates color layering similar to actual paint.

On Fine-Tuning

Most of the implementation is about recreating the physics, but I feel like parameter tuning can only be done by eye.

For example, the thickness of white lines. Initially I had them the same as other colors, but they felt too prominent.

1/3 → Still too thick
1/6 → Too thin
1/5 → Just right
Enter fullscreen mode Exit fullscreen mode

This "just right" can't be derived logically—it's a cycle of looking, feeling, and adjusting.

The same goes for the wobble amount. Too much and it looks like "a person with tremors," too little and it feels "mechanical." The subtle range of 0.25–0.65px was the result of many comparisons.

In the end, code can recreate physical phenomena, but I think deciding "this is good enough" comes down to human eyes and intuition.

Conclusion

Pendulum physics → Fractals → Visual resonance → A sense of calm

Perhaps what Pollock was doing was capturing this chain as paintings.

What I've come to think through this recreation is that the boundary between "art" and "physics" is surprisingly blurry. If the result of letting a pendulum do its thing is beautiful, maybe that means the laws of nature themselves are beautiful.

You might enjoy trying different color schemes or tweaking the parameters.

References

Top comments (0)