<h1><span>by</span> Enrico Toniato <a href="http://enricotoniato.com" target="_blank">enricotoniato.com</a></h1>
body {
  background:#2196F3;
  h1 {
    position: fixed;
    text-align:center;
    bottom:10px;
    left:30px;
    color:white;
    font-size: 20px;
    font-family: Roboto;
    font-weight: normal;
    z-index:999;
    span{
      font-size:15px;
      font-weight: lighter;
    }
    a{
      color:white;
      font-size:15px;
      padding: 0 30px

    }
  }
}
#notFound {
  position: fixed;
  top:50%;
  left:50%;
  transform:translateY(-50%) translateX(-50%) scale(1.2);
  width:80%;
  height:auto;
  
}
//animation frame polyfill
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() {
                    callback(currTime + timeToCall);
                },
                timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

//math2 utils
var Math2={};Math2.random=function(t,n){return Math.random()*(n-t)+t},Math2.map=function(t,n,r,a,o){return(o-a)*((t-n)/(r-n))+a},Math2.randomPlusMinus=function(t){return t=t?t:.5,Math.random()>t?-1:1},Math2.randomInt=function(t,n){return n+=1,Math.floor(Math.random()*(n-t)+t)},Math2.randomBool=function(t){return t=t?t:.5,Math.random()<t?!0:!1},Math2.degToRad=function(t){return rad=t*Math.PI/180,rad},Math2.radToDeg=function(t){return deg=180/(Math.PI*t),deg},Math2.rgbToHex=function(t){function n(t){return("0"+parseInt(t).toString(16)).slice(-2)}t=t.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);var r=n(t[1])+n(t[2])+n(t[3]);return r.toUpperCase()},Math2.distance=function(t,n,r,a){return Math.sqrt((r-t)*(r-t)+(a-n)*(a-n))};

//mouse
var mousePos={
  x:0,
  y:0
};
window.onmousemove = function(e) {
            
            e = e || window.event;

			var pageX = e.pageX;
			var pageY = e.pageY;
			if (pageX === undefined) {
				pageX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
				pageY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
			}
            mousePos = {
                x: pageX,
                y: pageY,
            };
        }
        
        

var options = {
        width: window.innerWidth,
        height: window.innerHeight,
        keyword : "404",
				density : 10,
				densityText : 3,
				minDist : 20,
    }
    // initialize canvas
var canvas = document.createElement('canvas');
canvas.width = options.width;
canvas.height = options.height;
canvas.style.width = options.width/2;
canvas.style.height = options.height/2;
canvas.getContext('2d').scale(2,2)

var renderer = new PIXI.autoDetectRenderer(options.width, options.height, {
    transparent: true
});
var stage = new PIXI.Stage("0X000000", true);
document.body.appendChild(renderer.view);
renderer.view.id = "notFound";







var imageData = false;
var particles =[]; 


function init() {
    positionParticles();
    positionText();
}

function positionParticles() {

    var canvas = document.createElement("canvas");
    canvas.width = 500;
    canvas.height = 350;
    var context = canvas.getContext("2d");
    context.fillStyle = "#000000";
    context.font = "300px 'Arial', sans-serif";
    context.fillText(options.keyword, 0, 250);

    var imageData = context.getImageData(0, 0, 350, 500);
    data = imageData.data;

    // Iterate each row and column
    for (var i = 0; i < imageData.height; i += options.density) {
        for (var j = 0; j < imageData.width; j += options.density) {

            // Get the color of the pixel
            var color = data[((j * (imageData.width * 4)) + (i * 4)) - 1];

            // If the color is black, draw pixels
            if (color == 255) {
                var newPar = particle()
                newPar.setPosition(i, j);
                particles.push(newPar);
                stage.addChild(newPar)
            }
        }
    }
}

function positionText() {
    var canvas = document.createElement("canvas");
    canvas.width = 400;
    canvas.height = 120;
    var context = canvas.getContext("2d");
    context.fillStyle = "#000000";
    context.font = "80px 'Arial', sans-serif";
    context.fillText("Not Found", 0, 80);

    var imageData = context.getImageData(0, 0, 400, 400);
    data = imageData.data;

    // Iterate each row and column
    for (var i = 0; i < imageData.height; i += options.densityText) {
        for (var j = 0; j < imageData.width; j += options.densityText) {

            // Get the color of the pixel
            var color = data[((j * (imageData.width * 4)) + (i * 4)) - 1];

            // If the color is black, draw pixels
            if (color == 255) {
                var newPar = particle(true)
                newPar.setPosition(i, j);
                particles.push(newPar);
                stage.addChild(newPar)
            }
        }
    }
}

function particle(text) {

    $this = new PIXI.Graphics()

    if (text == true) {
        $this.text = true;
    }

    $this.beginFill(0XFFFFFF);

    var radius;
    $this.radius = radius = $this.text ? Math.random() * 3.5 : Math.random() * 10.5;

    $this.drawCircle(0, 0, radius);

    $this.size = this.radius;
    $this.x = -this.width;
    $this.y = -this.height;
    $this.free = false;

    $this.timer = Math2.randomInt(0, 100);
    $this.v = Math2.randomPlusMinus() * Math2.random(.5, 1);
    $this.hovered = false

    $this.alpha = Math2.randomInt(10, 100) / 100;

    $this.vy = -5 + parseInt(Math.random() * 10) / 2;
    $this.vx = -4 + parseInt(Math.random() * 8);

    $this.setPosition = function(x, y) {
        if ($this.text) {
            $this.x = x + (options.width / 2 - 180);
            $this.y = y + (options.height / 2 + 100);
        } else {
            $this.x = x + (options.width / 2 - 250);
            $this.y = y + (options.height / 2 - 175);
        }
    };

    return $this;

}


function update() {
        
    renderer.render(stage);
        

    for (i = 0; i < particles.length; i++) {
        var p = particles[i];

        if (mousePos.x > p.x && mousePos.x < p.x + p.size && mousePos.y > p.y && mousePos.y < p.y + p.size) {
            p.hovered = true;
        }

        p.scale.x = p.scale.y = scale = Math.max(Math.min(2.5 - (Math2.distance(p.x, p.y, mousePos.x, mousePos.y) / 160), 160), 1);


        p.x = p.x + .2 * Math.sin(p.timer * .15)
        p.y = p.y + .2 * Math.cos(p.timer * .15)
        p.timer = p.timer + p.v;

    }
  window.requestAnimationFrame(update);
}

init();

update()

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/pixi.js/2.2.5/pixi.js