SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">

		<meta name="description" content="An infinitely hypnotic canvas animation" />
		<meta name="author" content="Hakim El Hattab" />

		<meta http-equiv="X-UA-Compatible" content="chrome=1">

		<title>Hypnos</title>

		<style>
			* {
				margin: 0;
				padding: 0;
			}

			html, body {
				height: 100%;
			}

			.main-container {
				width: 100%;
				height: 100%;
				background: #fff;
			}

			canvas {
				display: block;
				margin: 50px auto;
			}

			p {
				position: relative;
				text-align: center;
				margin-top: 10px;
				font-family: monospace;
			}

			.twitter-share-button {
				position: absolute !important;
				bottom: 10px;
				left: 50%;
				margin-left: -28px;
			}
		</style>

		<link href='https://fonts.googleapis.com/css?family=Molengo' rel='stylesheet' type='text/css'>

	</head>
	<body>

		<div class="main-container">

			<p>Hypnos by <a href="https://twitter.com/hakimel">@hakimel</a> / <a href="http://hakim.se">http://hakim.se</a></p>
			
			<canvas></canvas>

		</div>

		<script>

			/**
			 * Hypnos by Hakim El Hattab (@hakimel, http://hakim.se)
			 *
			 * Inspired by http://patakk.tumblr.com/post/33304597365
			 */
			(function() {

				var canvas = document.querySelector( 'canvas' ),
					context = canvas.getContext( '2d' ),

					width = window.innerWidth * 0.7,
					height = window.innerHeight * 0.7,

					radius = Math.min( width, height ) * 0.5,

					// Number of layers
					quality = 180,

					// Layer instances
					layers = [],

					// Width/height of layers
					layerSize = radius * 0.25,

					// Layers that overlap to create the infinity illusion
					layerOverlap = Math.round( quality * 0.1 );

				function initialize() {

					for( var i = 0; i < quality; i++ ) {
						layers.push({
							x: width/2 + Math.sin( i / quality * 2 * Math.PI ) * ( radius - layerSize ),
							y: height/2 + Math.cos( i / quality * 2 * Math.PI ) * ( radius - layerSize ),
							r: ( i / quality ) * Math.PI
						});
					}

					resize();
					update();

				}

				function resize() {

					canvas.width = width;
					canvas.height = height;

				}

				function update() {

					requestAnimationFrame( update );

					step();
					clear();
					paint();

				}

				// Takes a step in the simulation
				function step () {

					for( var i = 0, len = layers.length; i < len; i++ ) {

						layers[i].r += 0.01;

					}

				}

				// Clears the painting
				function clear() {

					context.clearRect( 0, 0, canvas.width, canvas.height );

				}

				// Paints the current state
				function paint() {

					// Number of layers in total
					var layersLength = layers.length;

					// Draw the overlap layers
					for( var i = layersLength - layerOverlap, len = layersLength; i < len; i++ ) {

						context.save();
						context.globalCompositeOperation = 'destination-over';
						paintLayer( layers[i] );
						context.restore();

					}

					// Cut out the overflow layers using the first layer as a mask
					context.save();
					context.globalCompositeOperation = 'destination-in';
					paintLayer( layers[0], true );
					context.restore();

					// // Draw the normal layers underneath the overlap
					for( var i = 0, len = layersLength; i < len; i++ ) {

						context.save();
						context.globalCompositeOperation = 'destination-over';
						paintLayer( layers[i] );
						context.restore();

					}

				}

				// Pains one layer
				function paintLayer( layer, mask ) {
					size = layerSize + ( mask ? 10 : 0 );
					size2 = size / 2;

					context.translate( layer.x, layer.y );
					context.rotate( layer.r );

					// No stroke if this is a mask
					if( !mask ) {
						context.strokeStyle = '#000';
						context.lineWidth = 1;
						context.strokeRect( -size2, -size2, size, size );
					}

					context.fillStyle = '#fff';
					context.fillRect( -size2, -size2, size, size );

				}

				/**
				 * rAF 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);
						};
				}());

				initialize();

			})();


		</script>

		<!-- Third party -->

		<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

		<script type="text/javascript">
		var _gaq = _gaq || [];
		_gaq.push(['_setAccount', 'UA-15240703-1']);
		_gaq.push(['_trackPageview']);

		(function() {
			var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
			ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
		})();
		</script>

	</body>
</html>
html{
  overflow: hidden;
}