Menu
Category

Author 27 Apr 2024 in Colors | 0 comments

VIEW DEMO   DOWNLOAD

Glowing Particle System with Different Shapes

Third part of my series where I build a Particle system with Canvas consisting of glowing particles with different shapes (circles and squares for now, read comments, it tells you a bit more about other shapes like stars).

HTML

Code
<canvas id="canvas"></canvas>


CSS

Code
html, body {
  margin: 0; padding: 0;
  width: 100%; height: 100%;
   
  overflow: hidden;
  background: #171819;
}


JavaScript

Code
// Get the canvas DOM element along with it's 2D context
// which is basically what we do our work on

var canvas = document.getElementById('canvas'),
  ctx = canvas.getContext('2d'),
  window_width = window.innerWidth,
  window_height = window.innerHeight;

// Set canvas's width and height to that
// of window (the view port)
canvas.width = window_width;
canvas.height = window_height;

// Just a random object name to store some utility
// functions that we can use later
var $$ = {
  // Get a random integer from a range of ints
  // Usage: $$.randomInt(4, 8) -> would return
  // 4 or 5 or 6 or 7 or 8
  randomInt: function(min, max) {
  return Math.random() * (max - min + 1) + min;
  }
};

// Pool of particles. Basically an array that stores all
// our particles
var particles = [];

// The object that'll serve as the prototype
// of every particle we create!
var Particle = {
  x: window_width/2,
  y: window_height/2,
  x_speed: 10,
  y_speed: 10,
  radius: 10,
  _position: {},
   
  // You can include other shapes like:
  //
  // Spirograph: https://developer.mozilla.org/samples/canvas-tutorial/5_4_canvas_scale.html
  // Star: http://blog.michelledinan.com/03/2012/html5-canvas-paths/ http://carisenda.com/blog/2012/howto-draw-a-star-with-canvas.html
  //
  // Fitting them in the experiment will require quite
  // a bit of Math to calculate subsequent x and y positions.
  shapes_list: ['circle', 'rectangle'],
   
  // Draw the particle
  draw: function() {
  var gradient;
   
  if (this.shape === 'rectangle') {
  gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
  gradient.addColorStop(0, 'white');
  gradient.addColorStop(0.5, this.bg_color);
  gradient.addColorStop(1, 'black');
   
  ctx.fillStyle = gradient;
   
  ctx.fillRect(
  this.x-this.radius,
  this.y-this.radius,
  this.radius*2,
  this.radius*2
  );
  }
  else {
  // Begin Drawing Path
  ctx.beginPath();
   
  gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius);
  gradient.addColorStop(0, 'white');
  gradient.addColorStop(1, this.bg_color);
   
  // Background color for the object that we'll draw
  ctx.fillStyle = gradient;
  // Draw the arc
  // ctx.arc(x, y, radius, start_angle, end_angle, anticlockwise)
  // angle are in radians
  // 360 degrees = 2π radians or 1 radian = 360/2π = 180/π degrees
  ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
  // Close Drawing Path
  ctx.closePath();
  // Fill the canvas with the arc
  ctx.fill();
  }
  },
   
  // These are just some helpers that
  // I've created, got no use in this
  // creation. These might give you some idea
  // to do some funky things .. Who knows ? <img src="http://s68.ucoz.net/sm/24/smile.gif" border="0" align="absmiddle" alt="smile" />
  trackPosition: function() {
  var position = {x: this.x, y: this.y};
   
  this._position.x = this.x;
  this._position.y = this.y;
  },
  getPosition: function() {
  return this._position;
  }
};

function createParticle() {
  if (particles.length > 50)
  return;
   
  // Create a particle object and use `Particle`
  // as the prototype of the object. I hope you know
  // about prototypes right ? Prototypal Inheritance, nope ? :S
  var particle = Object.create(Particle);
   
  // Set random initial positions
  particle.x = Math.random()*window_width;
  particle.y = Math.random()*window_height;
   
  // Random number between -5 and 5 using
  // our utility function, that was defined above.
  particle.x_speed = $$.randomInt(-3, 3);
  particle.y_speed = $$.randomInt(-3, 3);
   
  // Set the new particle's background color
  // HSLA FTW!
  // I think we're bored of plain simple colors.
  // We need some gradients awesomeness to make some
  // glowing particles.
  particle.bg_color = "hsla("+$$.randomInt(0,360)+", 80%, 50%, 0.5)";
   
  // Shape ?
  particle.shape = particle.shapes_list[Math.floor($$.randomInt(0,particle.shapes_list.length-1))];
   
  // Push the newly created particle
  // into our master array
  particles.push(particle);
}

function repaint() {
  // Clear the entire Canvas
  // It's important to understand Canvas Compositing
  // https://developer.mozilla.org/en-US/docs/Canvas_tutorial/Compositing
  ctx.globalCompositeOperation = "source-over";
  ctx.clearRect(0, 0, window_width, window_height);
  ctx.globalCompositeOperation = "lighter";
   
  // Re-draw all particles we have in our bag!
  for (var i = 0; i < particles.length; i++) {
  var particle = particles[i];
   
  particle.draw();
   
  // These conditional make sure that as soon
  // as a particle moves out of the view_port
  // It get's re-positioned to the exact opposite
  // side. Simple math, nothin fancy <img src="http://s68.ucoz.net/sm/24/wink.gif" border="0" align="absmiddle" alt="wink" />
  if (particle.x > window_width) {
  particle.x = 0 - particle.x_speed;
  } else if (particle.x < 0) {
  particle.x = window_width - particle.x_speed;
  } else if (particle.y > window_height) {
  particle.y = 0 - particle.y_speed;
  } else if (particle.y < 0) {
  particle.y = window_height - particle.y_speed;
  }
   
  // Changing x and y co-ordinates which
  // are random (generated in createParticle())
  //
  // This is cool, as we get different
  // speed for each particles then!
  particle.x = particle.x + particle.x_speed;
  particle.y = particle.y + particle.y_speed;
   
  // Track new position
  // Just a helper that might give you some
  // cool ideas to make some unique twists to this
  // experiment.
  particle.trackPosition();
  }
}

// Magic method for animation!
setInterval(function() {
  createParticle();
  repaint();
}, 1000/60);

Views: 994 | Rating: 0.0/0

Leave a comment

%