SOURCE

console 命令行工具 X clear

                    
>
console
// Context Free Art Javascript
"use strict";
const cfa = {
	canvas: document.querySelector("canvas"),
	stack: [],
	draws: [],
	// affine adjustments
	ajustments: {
		x(m, v) {
			m[4] += v * m[0];
			m[5] += v * m[1];
		},
		y(m, v) {
			m[4] += v * m[2];
			m[5] += v * m[3];
		},
		z(m, v) {
			m[11] += v;
		},
		rotate(m, v) {
			const rad = Math.PI * v / 180;
			const cos = Math.cos(rad);
			const sin = Math.sin(rad);
			const r00 = cos * m[0] + sin * m[2];
			const r01 = cos * m[1] + sin * m[3];
			m[2] = cos * m[2] - sin * m[0];
			m[3] = cos * m[3] - sin * m[1];
			m[0] = r00;
			m[1] = r01;
		},
		scale(m, v) {
			let x, y;
			if (Array.isArray(v)) {
				x = v[0];
				y = v[1];
			} else {
				x = v;
				y = x;
			}
			m[0] *= x;
			m[1] *= x;
			m[2] *= y;
			m[3] *= y;
		},
		// colors adjust
		hue(m, v) {
			m[6] += v;
			m[6] %= 360;
		},
		sat(m, v) {
			this.adjustColor(m, v, 7);
		},
		bri(m, v) {
			this.adjustColor(m, v, 8);
		},
		alpha(m, v) {
			this.adjustColor(m, v, 9);
		},
		adjustColor(m, v, p) {
			if (v > 0) {
				m[p] += v * (1 - m[p]);
			} else {
				m[p] += v * m[p];
			}
		},
		raf(m, v) {
			m[10] = v ? 1 : 0;
		}
	},
	normal(s, e) {
  	let rand = (Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()) / 6;
		return s + rand * (e - s);
	},
	random(s, e) {
		return s + Math.random() * (e - s);
	},
	adjust(s, p) {
		const m = [
			s[0],  // a00
			s[1],  // a10
			s[2],  // a01
			s[3],  // a11
			s[4],  // tx
			s[5],  // ty
			s[6],  // hue
			s[7],  // saturation
			s[8],  // brillance
			s[9],  // alpha
			s[10], // z-index
			s[11], // raf
			s[12]  // primitive
		];
		for (const c in p) {
			this.ajustments[c](m, p[c]);
		}
		return m;
	},
	// primitives
	setTransform(s) {
		this.ctx.setTransform(
			-this.scale * s[0],
			this.scale * s[1],
			this.scale * s[2],
			-this.scale * s[3],
			this.scale * s[4] + this.offsetX,
			-this.scale * s[5] + this.offsetY
		);
	},
	SQUARE(s, p = null) {
		this.primitive(s, p, 1);
	},
	primitive(s, p, i) {
		p && (s = this.adjust(s, p));
		s[12] = i;
		this.draws.push(s);
		this.bbox(s);
	},
	1(s) {
		// SQUARE
		this.setTransform(s);
		this.fillStyle(s);
		this.ctx.fillRect(-0.5, -0.5, 1, 1);
	},
	fillStyle(s) {
		this.ctx.fillStyle = `hsla(${Math.round(s[6])},${Math.round(
			s[7] * 100
		)}%,${Math.round(s[8] * 100)}%,${s[9]})`;
	},
	bbox(s) {
		const x = s[4] * this.scale;
		const y = s[5] * this.scale;
		if (x < this.rect[0]) this.rect[0] = x;
		else if (x > this.rect[1]) this.rect[1] = x;
		if (y < this.rect[2]) this.rect[2] = y;
		else if (y > this.rect[3]) this.rect[3] = y;
	},
	center(s) {
		const br = this.rect;
		const scale =
			Math.min(this.width / (br[1] - br[0]), this.height / (br[3] - br[2])) * s;
		this.scale *= scale;
		this.offsetX = this.width * 0.5 - (br[0] + br[1]) * 0.5 * scale;
		this.offsetY = this.height * 0.5 + (br[3] + br[2]) * 0.5 * scale;
	},
	// rendering iterator
	next () {
		requestAnimationFrame(_ => this.iter.next());
	},
	*render() {
		let s = 0;
		for (const draw of this.draws) {
			this[draw[12]](draw);
			if (s++ > this.speed && draw[10]) {
				s = 0;
				this.speed *= this.acc;
				if (this.speed < 1) this.speed = 1;
				yield this.next();
			}
		}
		yield this.next();
	},
	// call shape
	rule(name, s, p) {
		s = this.adjust(s, p);
		const x = (s[0] * s[0] + s[1] * s[1]) * this.scale;
		const y = (s[2] * s[2] + s[3] * s[3]) * this.scale;
		if (x < this.minSize && y < this.minSize) {
			// too small
			return;
		}
		s[12] = this.shape[name] * 1;
		this.stack.push(s);
	},
	run(code) {
		// inject code
		this.shape = {};
		let k = 3;
		for (const rule in code) {
			this.shape[rule] = k;
			this[k++] = code[rule];
		}
		// reset canvas
		this.ctx = this.canvas.getContext("2d");
		this.width = this.canvas.width = this.canvas.offsetWidth * 2;
		this.height = this.canvas.height = this.canvas.offsetHeight * 2;
		if (code.setup.background) {
			this.ctx.fillStyle = code.setup.background;
			this.ctx.fillRect(0, 0, this.width, this.height);
		}
		// init setup
		this.rect = [0, 0, 0, 0];
		this.stack.length = 0;
		this.draws.length = 0;
		this.scale = 100;
		this.speed = code.setup.speed || 100;
		this.minSize = code.setup.minSize || 1.0;
		this.acc = code.setup.acc || 1.0;
		// push start shape
		this.rule(code.setup.start, [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0], false);
		// run rules
		const t1 = performance.now();
		let iter = 0;
		do {
			iter++;
			const s = this.stack.shift();
			this[s[12]](s);
		} while (this.stack.length);
		const t2 = performance.now();
		console.log(iter, t2 - t1);
		// zSorting
		if (code.setup.zSorting) {
			this.draws.sort(function(d0, d1) {
				return d0[11] - d1[11];
			});
		}
		// centering
		this.center(code.setup.zoom || 1.0);
		// start rendering loop
		this.iter && (this.iter.return());
		this.iter = this.render();
		this.iter.next();
	}
};
["click", "touchdown"].forEach(event => {
	document.addEventListener(event, e => cfa.run(code), false);
});
/////////////////////////////////////////////
// Adapted from https://www.contextfreeart.org/gallery2/index.html#design/3748
// Living curves by mikelovesrobots, September 18th, 2016
const code = {
	setup: {
		background: "#000",
		minSize: 4,
		zoom: 1,
		speed: 1000,
		start: "init"
	},
	init(s) {
		this.rule('stroke', s, {hue: Math.random() * 90, sat: 1, bri: 0.5});
	},
	stroke(s) {
		const curve = this.normal(-4, 4);
		for (let i = 0; i < 368; i++) {
			s = this.adjust(s, {rotate: curve, y: 0.5});
			this.SQUARE(s, {scale:4, rotate: 45});
		}
		this.rule('stroke', s, {scale: 0.9, alpha: -0.1});
		this.rule('stroke', s, {scale: 0.5, alpha: -0.9});
	}
};
cfa.run(code);
<canvas></canvas>
<!-- Click to generate a new image -->
html, body {
	overflow: hidden;
	touch-action: none;
	content-zooming: none;
	position: absolute;
	margin: 0;
	padding: 0;
	width: 100%;
	height: 100%;
	background: #fff;
}

canvas {
	position: absolute;
	width: 100%;
	height: 100%;
	user-select: none;
	cursor: pointer;
}