SOURCE

console 命令行工具 X clear

                    
>
console
var SCREEN_WIDTH = window.innerWidth,
		SCREEN_HEIGHT = window.innerHeight,
		mousePos = {
			x: 400,
			y: 300
		},

// create canvas
		canvas = document.createElement('canvas'),
		context = canvas.getContext('2d'),
		particles = [],
		rockets = [],
		MAX_PARTICLES = 400,
		colorCode = 0;

// init
$(document).ready(function() {
	document.body.appendChild(canvas);
	canvas.width = SCREEN_WIDTH;
	canvas.height = SCREEN_HEIGHT;
	setInterval(launch, 800);
	setInterval(loop, 1000 / 50);
});

// update mouse position
$(document).mousemove(function(e) {
	e.preventDefault();
	mousePos = {
		x: e.clientX,
		y: e.clientY
	};
});

// launch more rockets!!!
$(document).mousedown(function(e) {
	for (var i = 0; i < 5; i++) {
		launchFrom(Math.random() * SCREEN_WIDTH * 2 / 3 + SCREEN_WIDTH / 6);
	}
});

function launch() {
	launchFrom(mousePos.x);
}

function launchFrom(x) {
	if (rockets.length < 10) {
		var rocket = new Rocket(x);
		rocket.explosionColor = Math.floor(Math.random() * 360 / 10) * 10;
		rocket.vel.y = Math.random() * -3 - 4;
		rocket.vel.x = Math.random() * 6 - 3;
		rocket.size = 8;
		rocket.shrink = 0.999;
		rocket.gravity = 0.01;
		rockets.push(rocket);
	}
}

function loop() {
	// update screen size
	if (SCREEN_WIDTH != window.innerWidth) {
		canvas.width = SCREEN_WIDTH = window.innerWidth;
	}
	if (SCREEN_HEIGHT != window.innerHeight) {
		canvas.height = SCREEN_HEIGHT = window.innerHeight;
	}

	// clear canvas
	context.fillStyle = "rgba(0, 0, 0, 0.05)";
	context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

	var existingRockets = [];

	for (var i = 0; i < rockets.length; i++) {
		// update and render
		rockets[i].update();
		rockets[i].render(context);

		// calculate distance with Pythagoras
		var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y - rockets[i].pos.y, 2));

		// random chance of 1% if rockets is above the middle
		var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false;

		/* Explosion rules
		 - 80% of screen
		 - going down
		 - close to the mouse
		 - 1% chance of random explosion
		 */
		if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || distance < 50 || randomChance) {
			rockets[i].explode();
		} else {
			existingRockets.push(rockets[i]);
		}
	}

	rockets = existingRockets;

	var existingParticles = [];

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

		// render and save particles that can be rendered
		if (particles[i].exists()) {
			particles[i].render(context);
			existingParticles.push(particles[i]);
		}
	}

	// update array with existing particles - old particles should be garbage collected
	particles = existingParticles;

	while (particles.length > MAX_PARTICLES) {
		particles.shift();
	}
}

function Particle(pos) {
	this.pos = {
		x: pos ? pos.x : 0,
		y: pos ? pos.y : 0
	};
	this.vel = {
		x: 0,
		y: 0
	};
	this.shrink = .97;
	this.size = 2;

	this.resistance = 1;
	this.gravity = 0;

	this.flick = false;

	this.alpha = 1;
	this.fade = 0;
	this.color = 0;
}

Particle.prototype.update = function() {
	// apply resistance
	this.vel.x *= this.resistance;
	this.vel.y *= this.resistance;

	// gravity down
	this.vel.y += this.gravity;

	// update position based on speed
	this.pos.x += this.vel.x;
	this.pos.y += this.vel.y;

	// shrink
	this.size *= this.shrink;

	// fade out
	this.alpha -= this.fade;
};

Particle.prototype.render = function(c) {
	if (!this.exists()) {
		return;
	}

	c.save();

	c.globalCompositeOperation = 'lighter';

	var x = this.pos.x,
			y = this.pos.y,
			r = this.size / 2;

	var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
	gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
	gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")");
	gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");

	c.fillStyle = gradient;

	c.beginPath();
	c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
	
	c.closePath();
	c.fill();

	c.restore();
};

Particle.prototype.exists = function() {
	return this.alpha >= 0.1 && this.size >= 1;
};

function Rocket(x) {
	Particle.apply(this, [{
		x: x,
		y: SCREEN_HEIGHT}]);

	this.explosionColor = 0;
}

Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;

Rocket.prototype.explode = function() {
	var count = Math.random() * 10 + 80;

	for (var i = 0; i < count; i++) {
		var particle = new Particle(this.pos);
		var angle = Math.random() * Math.PI * 2;

		// emulate 3D effect by using cosine and put more particles in the middle
		var speed = Math.cos(Math.random() * Math.PI / 2) * 15;

		particle.vel.x = Math.cos(angle) * speed;
		particle.vel.y = Math.sin(angle) * speed;

		particle.size = 10;

		particle.gravity = 0.2;
		particle.resistance = 0.92;
		particle.shrink = Math.random() * 0.05 + 0.93;

		particle.flick = true;
		particle.color = this.explosionColor;

		particles.push(particle);
	}
};

Rocket.prototype.render = function(c) {
	if (!this.exists()) {
		return;
	}

	c.save();

	c.globalCompositeOperation = 'lighter';

	var x = this.pos.x,
			y = this.pos.y,
			r = this.size / 2;

	var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
	gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
	gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");

	c.fillStyle = gradient;

	c.beginPath();
	c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true);
	c.closePath();
	c.fill();

	c.restore();
};

<canvas></canvas>
body {
  background-color: #000000;
  margin: 0px;
  overflow: hidden;
}