/*
* RequestAnimationFrame polyfill by Erik Mller
*/
(function(){var b=0;var c=[“ms”,“moz”,“webkit”,“o”];for(var a=0;a<&&!;++a){=window[c[a]+“RequestAnimationFrame”];=window[c[a]+“CancelAnimationFrame”]||window[c[a]+“CancelRequestAnimationFrame”]}if(!){=function(h,e){var d=new Date().getTime();var f=(0,16-(d-b));var g=(function(){h(d+f)},f);b=d+f;return g}}if(!){=function(d){clearTimeout(d)}}}());
/*
* Point class
*/
var Point = (function() {
function Point(x, y) {
= (typeof x !== ‘undefined’) x : 0;
= (typeof y !== ‘undefined’) y : 0;
}
= function() {
return new Point(, );
};
= function(length) {
if (typeof length == ‘undefined’)
return ( * + * );
();
*= length;
*= length;
return this;
};
= function() {
var length = ();
/= length;
/= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var Particle = (function() {
function Particle() {
= new Point();
= new Point();
= new Point();
= 0;
}
= function(x, y, dx, dy) {
= x;
= y;
= dx;
= dy;
= dx * ;
= dy * ;
= 0;
};
= function(deltaTime) {
+= * deltaTime;
+= * deltaTime;
+= * deltaTime;
+= * deltaTime;
+= deltaTime;
};
= function(context, image) {
function ease(t) {
return (–t) * t * t + 1;
}
var size = * ease( / );
= 1 - / ;
(image, - size / 2, - size / 2, size, size);
};
return Particle;
})();
/*
* ParticlePool class
*/
var ParticlePool = (function() {
var particles,
firstActive = 0,
firstFree = 0,
duration = ;
function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var i = 0; i < ; i++)
particles[i] = new Particle();
}
= function(x, y, dx, dy) {
particles[firstFree].initialize(x, y, dx, dy);
// handle circular queue
firstFree++;
if (firstFree == ) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == ) firstActive = 0;
};
= function(deltaTime) {
var i;
// update active particles
if (firstActive < firstFree) {
for (i = firstActive; i < firstFree; i++)
particles[i].update(deltaTime);
}
if (firstFree < firstActive) {
for (i = firstActive; i < ; i++)
particles[i].update(deltaTime);
for (i = 0; i < firstFree; i++)
particles[i].update(deltaTime);
}
// remove inactive particles
while (particles[firstActive].age >= duration && firstActive != firstFree) {
firstActive++;
if (firstActive == ) firstActive = 0;
}
};
= function(context, image) {
// draw active particles
if (firstActive < firstFree) {
for (i = firstActive; i < firstFree; i++)
particles[i].draw(context, image);
}
if (firstFree < firstActive) {
for (i = firstActive; i < ; i++)
particles[i].draw(context, image);
for (i = 0; i < firstFree; i++)
particles[i].draw(context, image);
}
};
return ParticlePool;
})();
/*
* Putting it all together
*/
(function(canvas) {
var context = (‘2d’),
particles = new ParticlePool(),
particleRate = / , // particles/sec
time;
// get point on heart with -PI <= t <= PI
function pointOnHeart(t) {
return new Point(
160 * ((t), 3),
130 * (t) - 50 * (2 * t) - 20 * (3 * t) - 10 * (4 * t) + 25
);
}
// creating the particle image using a dummy canvas
var image = (function() {
var canvas = (‘canvas’),
context = (‘2d’);
= ;
= ;
// helper function to create the path
function to(t) {
var point = pointOnHeart(t);
= / 2 + * / 350;
= / 2 - * / 350;
return point;
}
// create the path
();
var t = -;
var point = to(t);
(, );
while (t < ) {
t += 0.01; // baby steps!
point = to(t);
(, );
}
();
// create the fill
= ‘#ea80b0’;
();
// create the image
var image = new Image();
= ();
return image;
})();
// render that thing!
function render() {
// next animation frame
requestAnimationFrame(render);
// update time
var newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
// clear canvas
(0, 0, , );
// create new particles
var amount = particleRate * deltaTime;
for (var i = 0; i < amount; i++) {
var pos = pointOnHeart( - 2 * * ());
var dir = ().length();
( / 2 + , / 2 - , , -);
}
// update and draw particles
(deltaTime);
(context, image);
}
// handle (re-)sizing of the canvas
function onResize() {
= ;
= ;
}
= onResize;
// delay rendering bootstrap
setTimeout(function() {
onResize();
render();
}, 10);
})((‘pinkboard’));