Expanded(Click to create art)

HTML
<canvas></canvas> <!-- Click to generate a new image -->
CSS
html, body { overflow: hidden; touch-action: none; content-zooming: none; position: absolute; margin: 0; padding: 0; width: 100%; height: 100%; background: #999999; } canvas { position: absolute; width: 100vw; height: 100vw; max-height: 100vh; max-width: 100vh; margin: auto; top:0; bottom:0; left:0; right:0; user-select: none; cursor: pointer; background: #999999; }
JAVASCRIPT
// CFDG core functions (direct draws version) "use strict"; const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); let width, height, scale, offsetX, offsetY, minSize; const transforms = { 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]; }, s(m, v) { m[0] *= v[0]; m[1] *= v[0]; m[2] *= v[1]; m[3] *= v[1]; }, r(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; }, f(m, v) { const rad = Math.PI * v / 180; const x = Math.cos(rad); const y = Math.sin(rad); const n = 1 / (x * x + y * y); const b00 = (x * x - y * y) / n; const b01 = 2 * x * y / n; const b10 = 2 * x * y / n; const b11 = (y * y - x * x) / n; const r00 = b00 * m[0] + b01 * m[2]; const r01 = b00 * m[1] + b01 * m[3]; m[2] = b10 * m[0] + b11 * m[2]; m[3] = b10 * m[1] + b11 * m[3]; m[0] = r00; m[1] = r01; }, skew(m, v) { const x = Math.tan(Math.PI * v[0] / 180); const y = Math.tan(Math.PI * v[1] / 180); const r00 = m[0] + y * m[2]; const r01 = m[1] + y * m[3]; m[2] = x * m[0] + m[2]; m[3] = x * m[1] + m[3]; m[0] = r00; m[1] = r01; }, hue(m, v) { m[6] += v; m[6] %= 360; }, sat(m, v) { this.col(m, v, 7); }, b(m, v) { this.col(m, v, 8); }, a(m, v) { this.col(m, v, 9); }, col(m, v, p) { if (v > 0) { m[p] += v * (1 - m[p]); } else { m[p] += v * m[p]; } } }; const copy = s => { return [ 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 ]; }; const transform = (s, p) => { let m = copy(s); for (const c in p) { transforms[c](m, p[c]); } return m; }; const randint = (s, e = 0) => { if (e === 0) { e = s; s = 0; } return 1 + Math.floor(s + Math.random() * (e - s)); }; const loop = (n, s, t, f) => { let ls = copy(s); for (let i = 0; i < n; i++) { f(ls, i); ls = transform(ls, t); } }; const setTransform = s => { ctx.setTransform( -scale * s[0], scale * s[1], scale * s[2], -scale * s[3], scale * s[4] + offsetX, -scale * s[5] + offsetY ); }; const tooSmall = s => { const x = (s[0] * s[0] + s[1] * s[1]) * scale; const y = (s[2] * s[2] + s[3] * s[3]) * scale; return (x < minSize || y < minSize); } const hsla = s => { return `hsla(${Math.round(s[6])},${Math.round(s[7] * 100)}%,${Math.round( s[8] * 100 )}%,${s[9]})`; }; const SQUARE = (s, t) => { s = transform(s, t); setTransform(s); ctx.fillStyle = hsla(s); ctx.fillRect(-0.5, -0.5, 1, 1); }; const CIRCLE = (s, t) => { s = transform(s, t); setTransform(s); ctx.fillStyle = hsla(s); ctx.beginPath(); ctx.arc(0, 0, 0.5, 0, 2 * Math.PI); ctx.fill(); }; const TRIANGLE = (s, t) => { s = transform(s, t); setTransform(s); ctx.fillStyle = hsla(s); ctx.beginPath(); ctx.moveTo(0, 0.577350269); ctx.lineTo(-0.5, -0.28867513); ctx.lineTo(0.5, -0.28867513); ctx.lineTo(0.0, 0.577350269); ctx.closePath(); ctx.fill(); }; const INIT = (background, s, x, y, m) => { width = canvas.width = canvas.offsetWidth * 2; height = canvas.height = canvas.offsetHeight * 2; ctx.fillStyle = background; ctx.fillRect(0, 0, width, height); const r = Math.max(width, height) / 2048; scale = s * r; offsetX = x * (width / 2048); offsetY = y * (height / 2048); minSize = m; }; ["click", "touchdown"].forEach(event => { document.addEventListener(event, e => START(), false); }); ////////////////////////////////////////////////////////////////// // Adapted from a CFDG program // https://www.contextfreeart.org/gallery2/index.html#design/107 // kw-expanded by momo, September 23rd, 2005 ////////////////////////////////////////////////////////////////// const START = _ => { INIT("#999999", 170, 1024, 1024, 1); Scene([1, 0, 0, 1, 0, 0, 0, 0, 0, 1]); }; const Scene = s => { NODE(s, { hue: 40, sat: 0.8, b: 0.2 }); NODE(s, { hue: 40, sat: 0.8, b: 0.2, r: 90 }); NODE(s, { hue: 40, sat: 0.8, b: 0.2, r: 180 }); NODE(s, { hue: 40, sat: 0.8, b: 0.2, r: 270 }); }; const NODE = (s, t) => { s = transform(s, t); if (tooSmall(s)) return; const r = Math.random() * 1.4; let weight = 0; switch (true) { case r <= (weight += 0.2): NODE(s, {f: 17, skew:[0, 5]}); break; case r <= (weight += 0.2): NODE(s, {f: 197, skew:[8, 0]}); break; default: NODE(s, {y: 1.2, r: 35, skew:[5, 0], s:[0.89, 0.89], hue: -20.5, a: -0.02}); STAR(s, {skew:[0, 20]}); } }; const STAR = (s, t) => { s = transform(s, t); if (tooSmall(s)) return; SHAPE(s); SHAPE(s, {f: 180, a: -0.3}); SHAPE(s, {r: 90, a: -0.4}); SHAPE(s, {r:-90, a: -0.2}); STAR(s, {s:[0.65, 0.65], b: 0.25}); }; const SHAPE = (s, t) => { s = transform(s, t); const r = Math.random() * 1.4; let weight = 0; switch (true) { case r <= (weight += 0.2): SHAPE(s, {skew: [0, 10]}); break; case r <= (weight += 0.2): SHAPE(s, {skew: [10, 0]}); break; default: TRIANGLE(s, {x: -1.5, y: 1}); CIRCLE(s, {x: 1}); SQUARE(s, {x: 3, s:[1.5, 0.09]}); SQUARE(s, {x: 3, r: 5, s:[1.5, 0.09], a: -0.5}); } }; START();
Expand for more options Login