Picture by Brad Kunkle

Pixels


Pixels = function()
{
    //...

    function reset()
    {
        _canvas.width = _width;
        _canvas.height = _height;

        _context = _canvas.getContext( '2d' );
        _context.clearRect( 0, 0, _canvas.width, _canvas.height );

        var tmp = document.createElement( 'canvas' );
        tmp.width = _image.width;
        tmp.height = _image.height;

        var ctx = tmp.getContext( '2d' );
        ctx.drawImage( _image, 0, 0 );

        var img = ctx.getImageData( 0, 0, _image.width, _image.height );

        var iw = _image.width;
        var ih = _image.height;
        var ox = ( _width - iw ) >> 1;
        var oy = ( _height - ih ) >> 1;

        var p = _particles = new Particle();

        for( var x = 0; x < iw; ++x )
        {
            for( var y = 0; y < ih; ++y )
            {
                p = p.next = new Particle( x + ox, y + oy, getPixel( img, x, y ) );
            }
        }

        _bmd = _context.getImageData( 0, 0, _width, _height );
    }

    function render()
    {
        _context.clearRect( 0, 0, _width, _height );

        for( var i = 3, n = _bmd.width * _bmd.height * 4; i < n; i +=4 )
        {
            _bmd.data[ i ] -= 70;
        }

        var mx = _mouse.x;
        var my = _mouse.y;

        var p = _particles.next;

        do
        {
            var x = p.x;
            var y = p.y;
            var vx = p.vx;
            var vy = p.vy;
            var dx;
            var dy;

            if( _mouseDown )
            {
                dx = mx - x;
                dy = my - y;

                var dxy = Math.sqrt( dx * dx + dy * dy );

                vx -= ( dx / dxy ) * 2;
                vy -= ( dy / dxy ) * 2;
            }

            dx = ( p.ox - x ) * 0.1;
            dy = ( p.oy - y ) * 0.1;

            vx = ( vx + dx ) * 0.9;
            vy = ( vy + dy ) * 0.9;

            setPixel( _bmd, x, y, p.color );

            p.x = x + vx;
            p.y = y + vy;
            p.vx = vx;
            p.vy = vy;

            p = p.next;

        } while( p );

        _context.putImageData( _bmd, 0, 0 );

        setTimeout( render, 1000 / 60 );
    }

    function getPixel( bmd, x, y )
    {
        x = Math.min( Math.round( x ), bmd.width );
        y = Math.min( Math.round( y ), bmd.height );

        var index = ( y * bmd.width + x ) * 4;

        return {
            r: bmd.data[ index ],
            g: bmd.data[ ++index ],
            b: bmd.data[ ++index ],
            a: bmd.data[ ++index ]
        };
    }

    function setPixel( bmd, x, y, color )
    {
        x = Math.min( Math.round( x ), bmd.width );
        y = Math.min( Math.round( y ), bmd.height );

        var index = ( y * bmd.width + x ) * 4;

        bmd.data[ index ] = color.r;
        bmd.data[ ++index ] = color.g;
        bmd.data[ ++index ] = color.b;
        bmd.data[ ++index ] = color.a;
    }

    //...
};

Particle = function( x, y, color )
{
    this.next = null;

    this.x = x;
    this.y = y;

    this.ox = x;
    this.oy = y;

    this.vx = 0;
    this.vy = 0;

    this.color = color;
};