Image Washing Javascript Html Canvas Experiment
This is an experiment to create the effect of raindrops cleaning a picture.
The experiment conbines a particle system and the image pixels alpha channel to create the effect.
Restart
The experiment conbines a particle system and the image pixels alpha channel to create the effect.
Restart
var ctx = document.getElementById('canvas').getContext('2d');
var imgd = null;
var pix = null;
var n = 0;
var ps = null;
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
imgd = ctx.getImageData(0, 0, img.width, img.height);
pix = imgd.data;
n = pix.length;
invisible();
ps = new ParticleSystem();
ps.init(20, 0, 0, 600, 50);
setInterval(function() { ps.update(); ps.render(); }, 10);
}
img.src = 'landscape0.jpg';
function invisible() {
for (var i = 0; i < img.height; i++) {
for (var j = 0; j < img.width; j++) {
var idx = (i * img.width + j) * 4;
pix[idx + 3] = 0;
}
}
ctx.putImageData(imgd, 0, 0);
}
function Particle() {
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.r = 5;
this.time = 1;
this.life = 0;
this.alpha = 255;
this.setValues = function(x, y, vx, vy) {
this.x = x; this.y = y;
this.vx = vx; this.vy = vy;
this.time = 0;
this.life = Math.floor(Math.random() * 500);
}
this.setColor = function(color) {
this.color = color;
}
this.render = function() {
for (var i = -this.r; i <= this.r; i++) {
for (var j = -this.r; j <= this.r; j++) {
var idx = (Math.floor(this.y + i) * img.width + Math.floor(this.x + j)) * 4;
if (idx >= 0 && idx < pix.length && this.r * this.r > i * i + j * j) {
pix[idx + 3] = Math.min(255, pix[idx + 3] + 8);
}
}
}
}
}
function ParticleSystem() {
this.x0;
this.y0;
this.x1;
this.y1;
this.n = 0;
this.particles = [];
this.gravity = 0;
this.init = function(n, x0, y0, x1, y1) {
this.n = n;
this.x0 = x0; this.y0 = y0;
this.x1 = x1; this.y1 = y1;
this.gravity = 0;
for (var i = 0; i < n; i++) {
this.particles.push(new Particle());
this.particles[i].setValues(Math.floor(Math.random() * this.x1) + this.x0, Math.floor(Math.random() * this.y1) + this.y0, 0, 1);
}
}
this.setParticlesColor = function(color) {
for (var i = 0; i < this.particles.length; i++) this.particles[i].setColor(color);
}
this.update = function() {
for (var i = 0; i < this.particles.length; i++) {
if (this.particles[i].time < this.particles[i].life) {
this.particles[i].x = this.particles[i].x + (Math.floor(Math.random() * 3) - 1);
this.particles[i].y = this.particles[i].y + this.particles[i].vy;
this.particles[i].time += 1;
}
else {
this.particles[i].setValues(Math.floor(Math.random() * this.x1) + this.x0, Math.floor(Math.random() * this.y1) + this.y0, 0, 1)
}
}
}
this.render = function() {
for (var i = 0; i < this.particles.length; i++) { this.particles[i].render(); }
ctx.putImageData(imgd, 0, 0);
}
}