Wanna wholla lotta curves?


In my neverending exploration of the borderlands between code and poetry I came across this dark place where mysterious shapes reveal their haunting beauty for a fleeting moment before plunging back into the dark cyber abyss for the rest of eternity.

In other words, here's a simple proggie that animates quadratic curves on the HTML5 Canvas.

Finally something that looks really cool but is easy to code and does not require any math beyond the four basic operations that you learned by the 3rd grade - no trig, complex numbers or direct bitmap operations.

Let's jump right into the code:

<html>
<style>
body {
  background-colorblack;
}
</style>
<body>
<canvas id="myCanvaswidth="800height="600"></canvas>
<script>
const time = 255 * 2;
let x = [], y = [], speedX = [], speedY = [];
let redgreenbluerandomRedrandomGreenrandomBluecounterfade;
 
let canvas = document.getElementById('myCanvas');
let context = canvas.getContext('2d');
 
function reset() {
  counter = 0;
  randomRed = Math.random();
  randomGreen = Math.random();
  randomBlue = Math.random();
 
  for (let n = 0n < 5n++) {
    x[n] = Math.floor(Math.random() * canvas.width);
    y[n] = Math.floor(Math.random() * canvas.height);
    speedX[n] = -2 + Math.random() * 4;
    speedY[n] = -2 + Math.random() * 4;
  }
}
 
function animate() {
  context.clearRect(00canvas.widthcanvas.height);
 
  fade = Math.abs(time / 2 - counter);
  for (let n = 0n < 64n++) {
    green = n * 4 + 1;
    green = Math.max(green - fade0);
    green = green * randomGreen;
    blue = 255 - n * 4;
    blue = Math.max(blue - fade0);
    blue = blue * randomBlue;
    red = Math.max(randomRed * 256 - fade0);
    context.strokeStyle = 'rgba(' + red + ',' + green + ',' + blue + ',1)';
 
    context.beginPath();
    context.moveTo(x[0], y[0]);
    context.quadraticCurveTo(x[1], y[1], x[2] + n * 5y[2] + n * 5);
    context.quadraticCurveTo(x[3], y[3], x[4] + n * 5y[4] + n * n);
    context.quadraticCurveTo(x[1], y[1], x[0], y[0]);
    context.stroke();
  }
  counter++;
  if (counter == time)
    reset();
 
  for (let n = 0n < 5n++) {
    x[n] = x[n] + speedX[n];
    y[n] = y[n] + speedY[n];
  }
  window.requestAnimationFrame(animate);
 
reset();
window.requestAnimationFrame(animate);
</script>
</body>
</html>



Overview:

In a nutshell, we have 5 points on the screen. We draw 3 quadratic curves between them. For each of those curves, we draw 63 more, shifting the points a little bit each time and slightly changing the color.
In each animation frame, we move the 5 points. After about 500 frames we start a new set of curves: randomize the coordinates of the points, their speeds and the color of the curves.
The 'fade' factor decreases from 255 to 0 in the first half of a set (fade in) and then increases in the second half (fade out).

Here's how quadratic curves work:



To draw this white curve, first move the pen to point 0 (the beginning) and then do quadraticCurveTo(point 1, point2)
Point 2 is the end point. Point 1 is the control point - it determines the curvature between the beginning and the end. The red lines are only there to show where the control point is.
In our program, we add a second curve at the end of the first one (it's blue on this picture):



And a third one, back to the first one (green). This time I'm not including the supporting red lines. In our final program, all three curves (white, blue and green) will have one color. The three colors are used here to help you understand the mechanism of drawing the shape.



Look what happens if for each of those curves we draw similar ones, shifting some of the points by a bit:



So the curves themselves are relatively simple. It's the cloning with a shift that makes them look interesting and gives them a 3d feeling, resembling sails.

Now you know how to create the shape. The rest is just shifting the colors and animating the 5 points...


Details:

Lines [1-9] set up HTML5 Canvas
[10] time - how many frames one set of curves will remain on the screen
[11] coordinates and speeds of the points
[12-16] colors and other variables, HTML setup
[17-29] the 'reset' function creates a new set of curves by randomizing their parameters.
[31-61] this is the actual engine that does all the work:
[32] clear the previous frame. Removing this line leads to an interesting effect - try it!
[34] calculate the current fade factor
[35] the loop that draws 64 curves
[36] the green component of the curve RGB (Red/Green/Blue) color is proportional to the number of the curve (n)
[37] subtract the 'fade' factor. If the result is negative, use 0
[38] factor in the green randomization component for the given set
[39-41] the blue component is analogical to the green one, except the proportion is reversed
[42] the red component does not depend on the line number
[43] set the curve color calculated in [36-42]
[45] begin the curve
[46] move to point 0
[47] draw the first curve - to point 2
[48] draw the second curve - to point 4
[49] draw the third curve - back to point 0
[50] complete the curve
[52] increase the frame counter
[53-54] if the counter reaches the limit, start a new set of curves
[56-59] shift each point's coordinates using its speeds (x and y axles)
[60-61] this is the main program - it just creates the first set and kicks off the animation



Check out these programming tutorials:

JavaScript:

Optical illusion (18 lines)

Spinning squares - visual effect (25 lines)

Oldschool fire effect (20 lines)

Fireworks (60 lines)

Animated fractal (32 lines)

Physics engine for beginners

Physics engine - interactive sandbox

Physics engine - silly contraption

Starfield (21 lines)

Yin Yang with a twist (4 circles and 20 lines)

Tile map editor (70 lines)

Sine scroller (30 lines)

Interactive animated sprites

Image transition effect (16 lines)

Your first program in JavaScript: you need 5 minutes and a notepad


Fractals in Excel

Python in Blender 3d:

Domino effect (10 lines)


Wrecking ball effect (14 lines)

3d fractal in Blender Python