top of page
  • surajsubudhi10

Neon Arc Particle Animation with p5js

We are going to generate animated particles which create interesting arcs. We will be using the p5js library for rendering elements.


Final result preview:


We can use the p5js web editor which has all the necessary elements we need for drawing the arc. So when we open the editor we have very basic code as follows

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
}
  • Let's set both the width and height of the canvas as 800 which will make it a square.

  • For smooth animation we can set the frame rate to high as 60, here I'm putting it to 75.

  • In the draw function which will be getting called for each frame, we can draw all the elements there.

  • So let's set the background colour for the canvas to #28323F.

  • We need no strokes basically no border will be drawn for each element we draw on the canvas. refer noStroke()

  • We have to draw all the elements from the centre of the canvas instead of the left-top corner which is the default in p5js.

After all the steps we have the below code:

const CANVAS_SIZE = 800;

function setup() {
  createCanvas(CANVAS_SIZE, CANVAS_SIZE);
  frameRate(75);
  rectMode(CENTER);
}

function draw() {
  background("#28323F");
  noStroke();
  translate(width/2, height/2);
}
  • For drawing circles that represent particles in the canvas, we have to use the ellipse() function which takes a position as the first 2 arguments and the next 2 arguments will be the radius of the circle.

  • If we want to color the circle we can use the fill() function that takes RGB colours as arguments.

let particlePosX = 50;
let particlePosY = 50;
let particleRadius = 80;
  
fill(220, 120, 110);
ellipse(particlePosX, particlePosY, particleRadius,particleRadius);
  • The above code will draw just one particle and for our usage we have to use more particles as for the demo I will be using 900 particles. We can make a const variable where we can tweak this number.

  • So we need to add the above code inside the for-loop. And if draw the code we will not see any difference as all the particles are drawing on top of each other.

  • we can arrange all particles on a large circle and animate it.

const CIRCLE_RADIUS = 150;
// ...
let particlePos = CIRCLE_RADIUS;
let particlePosX = particlePos * cos(i);
let particlePosY = particlePos * sin(i);  
let particleRadius = 5;
  • Now all the circles are on a big circle we can also animate all the circles around the circumference of the circle with a sin() function which will give ranges of -1 to 1.

const FREQUENCY = 0.00002375;
let particlePos = CIRCLE_RADIUS + 100 * sin(frameCount * 500 * FREQUENCY);
  • We are very close to our final results. Now we have all the particles/circles that have the same speed and to add interesting effects we can change the speed of each particle as per their index, so instead of 500, we can use i(index) as their speed.

  • Setting different speeds for each particle we get very interesting animation effects for all the particles.

  • To make it more visually appealing we can change the size of particles as they move from their extreme positions. And also change the particle colours as we move our mouse.

const MAX_PARTICLE_RADIUS = 5;
const MIN_PARTICLE_RADIUS = 3;
// ...
let particleRadius = map(particlePos, CIRCLE_RADIUS, CIRCLE_RADIUS + 100, MIN_PARTICLE_RADIUS, MAX_PARTICLE_RADIUS);
let colorX = map(mouseX, 0, width, 150, 255);
let colorY = map(mouseY, 0, height, 0, 255);

fill(particlePos, colorX, colorY);

So our final code for getting the animated particles should be as below (refer my sketch):

const CANVAS_SIZE = 800;
const NUM_OF_PARTICLES = 900;
const FREQUENCY = 0.00002375;
const CIRCLE_RADIUS = 150;
const MAX_PARTICLE_RADIUS = 5;
const MIN_PARTICLE_RADIUS = 3;

function setup() {
  createCanvas(CANVAS_SIZE, CANVAS_SIZE);
  frameRate(75);
  rectMode(CENTER);
}

function draw() {
  background("#28323F");
  noStroke();
  translate(width/2, height/2);
  for (let i = 0; i < NUM_OF_PARTICLES; ++i)
  {
    let particlePos = CIRCLE_RADIUS + 100 * sin(frameCount * i * FREQUENCY);
    let particlePosX = particlePos * cos(i);
    let particlePosY = particlePos * sin(i);
    let particleRadius = map(particlePos, CIRCLE_RADIUS, CIRCLE_RADIUS + 100, MIN_PARTICLE_RADIUS, MAX_PARTICLE_RADIUS);
    
    let colorX = map(mouseX, 0, width, 150, 255);
    let colorY = map(mouseY, 0, height, 0, 255);
    
    fill(particlePos, colorX, colorY);
    ellipse(particlePosX, particlePosY, particleRadius, particleRadius);
  }
}

Comentarios


bottom of page