A Pen by Gary Constable.
Just experimenting with some particles.
A Pen by Gary Constable on CodePen.
<!--
just some more random particles and things..
-->
//utils and calcullations
var utils = {
lineLength : function(x, y, x0, y0){
return Math.sqrt((x -= x0) * x + (y -= y0) * y);
}
}
//particle
var particle = function(opts){
this.width = opts.width || 1;
this.height = opts.height || 1;
this.x_pos = opts.x_pos || 0;
this.y_pos = opts.y_pos || 0;
this.x_speed = opts.x_speed || Math.random()*10;
this.y_speed = opts.y_speed || Math.random()*10;
this.color = opts.color || 'rgb(255,255,255)';
this.canvas_width = opts.canvas_width || 800;
this.canvas_height = opts.canvas_width || 500;
this.draw = opts.draw || 'dot';
this.birth_state = this;
}
//the old move fuctions
particle.prototype.animate = function(width, height){
W = width;
H = height;
p = this;
p.y_pos += p.y_speed;
if(p.y_pos < -50) p.y_pos = H+50;
if(p.y_pos > H+50) p.y_pos = -50;
p.x_pos += p.x_speed;
if(p.x_pos < -50) p.x_pos = W+50;
if(p.x_pos > W+50) p.x_pos = -50;
}
/*
//move up and down within the mask / bounds area
particle.prototype.animate = function(){
p = this;
p.y_pos += p.y_speed;
}
*/
//revese the speed (and so the direction) of the particle
particle.prototype.reverseSpeed = function(){
//make negative
if(this.y_speed > 0){
//(20) * (-1)
this.y_speed = (this.y_speed) * (-1);
}else{
//(-20) * (-1)
this.y_speed = (this.y_speed) * (-1);
}
}
//https://raw2.github.com/garyconstable/cloaked-octo-hipster/develop/anchor.js
var anchor = function(opts){
this.radius = opts.radius || 0;
this.x_pos = opts.x_pos || 0;
this.y_pos = opts.y_pos || 0;
this.draw = opts.draw || 'circle';
this.lifespan = opts.draw || 2000;
this.created = new Date().getTime();
this.canvas_width = opts.canvas_width || 800;
this.canvas_height = opts.canvas_width || 500;
this.animate = function(){}
this.birth = this;
}
//particle factory - were already thing expansions....
var particleFactory = function(){};
particleFactory.prototype.create = function ( options, type ) {
switch(type){
case 'anchor' : return new anchor( options );
default: return new particle( options );
}
};
//canvas
var Canvas = function(options){
var self = this;
this.surface = options.surface || "canvas";
this.surface = document.getElementById(this.surface);
this.width = this.surface.offsetWidth;
this.height = this.surface.offsetHeight;
this.bounds;
this.non_bounds;
this.mask = [];
var ctx = this.surface.getContext('2d');
this.ctx = ctx;
}
//clear canvar
Canvas.prototype.clear = function(){
ctx = this.ctx;
ctx.clearRect ( 0 , 0 , this.width , this.height );
}
//pass to correct drawing function
Canvas.prototype.render = function(opts){
switch(opts.draw){
case 'dot' : this.dot(opts); break;
case 'circle' : this.circle(opts); break;
}
}
//draw point
Canvas.prototype.dot = function( opts ){
ctx.fillStyle = opts.color || 'rgb(255,255,255)';
ctx.fillRect(opts.x_pos,opts.y_pos,opts.width,opts.height);
}
//draw circle
Canvas.prototype.circle = function( opts ){
radius = opts.radius || 10;
color = opts.color || 'rgb(255,0,0)';
ctx.beginPath();
ctx.fillStyle = color;
ctx.arc(opts.x_pos, opts.y_pos, radius, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
Canvas.prototype.createBounds = function( opts ){
ctx = this.ctx;
// this is the unicode hex of a heart
//str = "2764";
str = "Hello...!";
fontStr = "150pt Helvetica Arial, sans-serif";
ctx.beginPath();
ctx.font = fontStr;
ctx.textAlign = "center";
ctx.fillStyle = "#ffffff";
//ctx.fillText(String.fromCharCode(parseInt(str, 16)),this.width/2 ,this.height - 50);
ctx.fillText( str, this.width/2 ,this.height/2);
ctx.closePath();
this.mask = ctx.getImageData(0,0,this.width,this.height);
area = [];
non_area =[];
// save all white pixels, these will be used as the bounds for the particles
//http://falcon80.com/HTMLCanvas/PixelManipulation/getImageData.html
//https://github.com/ottis/canvas-particles/blob/master/js/particle_system.js
for (var i = 0; i < this.mask.data.length; i+=4) {
if (this.mask.data[i] == 255 && this.mask.data[i+1] == 255 && this.mask.data[i+2] == 255 && this.mask.data[i+3] == 255) {
area.push([this.toPosX(i,this.mask.width),this.toPosY(i,this.mask.width)]);
}else{
//non_area.push([this.toPosX(i,mask.width),this.toPosY(i,mask.width)]);
}
}
this.bounds = area;
this.non_bounds = non_area;
}
Canvas.prototype.toPosX = function(i,w) {
return (i % (4 * w)) / 4;
}
Canvas.prototype.toPosY = function(i, w){
return Math.floor(i / (4 * w));
}
//get the color of the specifed pixel
Canvas.prototype.pixelColor = function(objectx, objecty){
var imageData = this.mask
var inputData = imageData.data;
var pData = (~~objectx + (~~objecty * this.mask.width)) * 4;
var r = inputData[pData],
g = inputData[pData + 1],
b = inputData[pData + 2],
a = inputData[pData + 3];
return [r,g,b,a];
}
Canvas.prototype.addToMask = function(obj){
var tc = Canvas;
console.log(tc);
var c = document.createElement('canvas');
c.id = "tc";
c.width = tc.width;
c.height = tc.height;
//this.canvas.bound.push(black pixel)
}
Canvas.prototype.removeFromMask = function(){
//this.canvas.bound.remove(black pixel)
}
// i think it would be better to keep this seperate
var particleSystem = function(options){
this.total_particles = 1000;
this.particles_drawn = 0;
this.particles = [ ];
this.nodes = [ ];
this.nodes_pointer = [ ];
this.canvas = options.canvas;
this.createParticles();
this.self = this;
}
//create the particles
particleSystem.prototype.createParticles = function(){
pf = new particleFactory();
w = this.canvas.width;
h = this.canvas.height;
x = 0;
y = 0;
/*
// create the particles, add base 2 number, higher = less particles
for(var i=0; i<this.canvas.bounds.length;i+=30){
this.particles.push( pf.create({
x_pos: this.canvas.bounds[i][0],
y_pos: this.canvas.bounds[i][1],
color: 'rgb(0,92,92)',
width: 3,
height: 3,
y_speed: Math.floor(Math.random() * 5) + 1
}) );
this.particles_drawn++;
}
*/
// create the particles, add base 2 number, higher = less particles
for(var i=0; i<this.total_particles; i++){
obj = pf.create({
x_pos: this.canvas.width / 2,
y_pos: (this.canvas.height / 8) * 7,
color: 'rgb(0,92,92)',
width: 6,
height: 6,
//y_speed: -5,
//y_speed: Math.floor(Math.random() * 5) + 1
})
//random num ->
num = Math.floor(Math.random() * 100) + 1;
//x speed
if(num < 51){
obj.x_speed = -(Math.floor(Math.random() * 5) + 1);
}
if(num > 50){
obj.x_speed = (Math.floor(Math.random() * 5) + 1);
}
//y speed
if(num < 51){
obj.y_speed = -(Math.floor(Math.random() * 5) + 1);
}
if(num > 50){
obj.y_speed = (Math.floor(Math.random() * 5) + 1);
}
this.particles.push( obj );
this.particles_drawn++;
}
}
//remove element from particle system array
particleSystem.prototype.remove = function(particle, index){
if (typeof particle.lifespan != "undefined") {
if( (new Date().getTime() - particle.created) > particle.lifespan){
return this.crop(index, particle.created);
}
}
return false;
}
//render loop clear canvas and redraw
particleSystem.prototype.render = function(self){
var i=0;
this.canvas.clear();
this.particles.forEach( function(particle) {
if( self.remove(particle, i) === false ){
//change the particle in some way
if (typeof particle.animate !== "undefined") {
/*
//get the pixel color
var pc = self.canvas.pixelColor(particle.x_pos, particle.y_pos);
//if its a black pixel
if(pc[0] == 0 && pc[1] == 0 && pc[2] == 0 && pc[3] == 0){
try{
particle.reverseSpeed();
}catch(ex){}
//contiune in the same direction..
}
*/
//move the particle
particle.animate( this.canvas.width, this.canvas.height );
}
//render the particle
Canvas.render(particle);
}//eo remove
i++;
});
}
//remove element from particles array
particleSystem.prototype.crop = function(index, ts){
//remove from the drawing array
this.particles.splice(index, 1);
this.particles_drawn--;
//remove the node pointers to the node
var i = this.nodes_pointer.indexOf(ts);
if(i !== -1){
this.nodes.splice(i, 1);
this.nodes_pointer.splice(i, 1);
//console.log(self.nodes);
}
return true;
}
//app
var App = function(options){
//create a canvas and add to body
var c = document.createElement('canvas');
c.id = "canvas";
c.width = 800;
c.height = 500;
c.style.border = "1px solid white";
document.getElementsByTagName("body")[0].style.background = 'black';
document.getElementsByTagName("body")[0].appendChild(c);
//create canvas obj and mouselistener
Canvas = new Canvas({ 'surface' : 'canvas' });
//create the shape
//Canvas.createBounds();
//create the particle system obj
this.ps = new particleSystem({'canvas' : Canvas})
self = this;
}
//render loop
App.prototype.run = function(){
self.ps.render(self.ps);
requestAnimationFrame( self.run );
}
//animation frame
window.requestAnimFrame = (function(){
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
//init + animate + the go button..
var app = new App().run();