Barnsley fern
Inspired by a Youtube video: Chaos Game - Numberphile
Learn more about how this works at Wikipedia: https://en.wikipedia.org/wiki/Barnsley_fern
Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<canvas id="mycanvas" width="960" height="500"></canvas>
<script>
var canvas = document.getElementById('mycanvas'),
ctx = canvas.getContext('2d'),
i = 0,
dot = {
x: 0,
y: 0,
hue: 0.001,
lightness: 0.35
};
// https://en.wikipedia.org/wiki/Barnsley_fern#Construction
var barnsley = [
{a: 0.00, b: 0.00, c: 0.00, d: 0.16, e: 0.00, f: 0.00, p: 0.01},
{a: 0.85, b: 0.04, c: -0.04, d: 0.85, e: 0.00, f: 1.60, p: 0.01 + 0.85},
{a: 0.20, b: -0.26, c: 0.23, d: 0.22, e: 0.00, f: 1.60, p: 0.01 + 0.85 + 0.07},
{a: -0.15, b: 0.28, c: 0.26, d: 0.24, e: 0.00, f: 0.44, p: 0.01 + 0.85 + 0.07 + 0.07}
];
function fern_step(obj) {
var p = Math.random();
var b = null;
for (i = 0; i < barnsley.length; i++) {
b = barnsley[i];
if (p < b.p) {
return Object.assign(obj, {
x: b.a * obj.x + b.b * obj.y + b.e,
y: b.c * obj.x + b.d * obj.y + b.f,
hue: p < 1e-3 ? (obj.hue > 1 ? 1e-4 : obj.hue + 1e-3) : obj.hue
// hue: 0.4
});
}
}
}
// Keep track of how many frames we draw.
var frames = 0;
function step() {
// Stop drawing frames after some limit.
if (frames++ > 1e3) {
return;
}
// Draw a variable number of points each frame.
for (var k = 0; k < frames; k++) {
draw_circle(
ctx,
dot.x * 105 + canvas.width / 2,
dot.y * -49 + canvas.height,
0.09, // radius
dot.hue, // hue
dot.lightness // lightness
);
dot = fern_step(dot);
}
// Draw another frame.
window.requestAnimationFrame(step);
}
// Draw a frame.
window.requestAnimationFrame(step);
function draw_circle(ctx, x, y, radius, hue, lightness) {
ctx.fillRect(x, y, 1, 1);
var rgb = hslToRgb(hue, 0.75, lightness);
ctx.fillStyle = 'rgba(' +
rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + 0.5 +
')';
ctx.fill();
}
/**
* https://stackoverflow.com/a/9493060/330558
*
* Converts an HSL color value to RGB. Conversion formula
* adapted from https://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param {number} h The hue
* @param {number} s The saturation
* @param {number} l The lightness
* @return {Array} The RGB representation
*/
function hslToRgb(h, s, l){
var r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
</script>
</body>