X

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


		
		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);
            }

        }