Skip to content

Instantly share code, notes, and snippets.

@perliedman
Created March 5, 2016 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perliedman/58e4a0a850af80eed00e to your computer and use it in GitHub Desktop.
Save perliedman/58e4a0a850af80eed00e to your computer and use it in GitHub Desktop.
Fern fractal
<html>
<head>
<title></title>
<style type="text/css">
body {
background-color: black;
padding: 0;
margin: 0;
}
#canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
var canvas = document.querySelector('#canvas'),
body = document.querySelector('body');
canvas.width = body.offsetWidth;
canvas.height = body.offsetHeight;
var width = canvas.width,
height = canvas.height,
scale = Math.min(width, height) / 10,
offset = [-width / 2 / scale, 0],
maxPass = 6,
dalpha = 8,
ctx = canvas.getContext('2d'),
timer;
var coefs = [
{
coefs: [0, 0, 0, 0.16, 0, 0],
p: 0.01
},
{
coefs: [0.85, 0.04, -0.04, 0.85, 0, 1.6],
p: 0.85
},
{
coefs: [0.2, -0.26, 0.23, 0.22, 0, 1.6],
p: 0.07
},
{
coefs: [-0.15, 0.28, 0.26, 0.24, 0, 0.44],
p: 0.07
}
],
table = coefs.reduce(function(ts, c) {
var prevP = ts.length ? ts[ts.length - 1].p : 0;
ts.push({coefs: c.coefs, p: prevP + c.p});
return ts;
}, []);
var x = 0,
y = 0,
pass = 0,
canvasData = ctx.getImageData(0, 0, width, height);
function render() {
function drawPixel (x, y, r, g, b) {
if (x < 0 || x >= width || y < 0 || y >= height) return;
var index = (Math.round(x) + (height - Math.round(y)) * width) * 4;
canvasData.data[index + 0] = r;
canvasData.data[index + 1] = g;
canvasData.data[index + 2] = b;
canvasData.data[index + 3] += dalpha;
}
for (var i = 0; i < 400000; i++) {
var r = Math.random(),
j = 0;
for (j; r > table[j].p; j++);
var c = table[j].coefs;
var nx = x * c[0] + y * c[1] + c[4];
y = x * c[2] + y * c[3] + c[5];
x = nx;
drawPixel((x - offset[0]) * scale, (y - offset[1]) * scale, 135, 224, 64);
}
pass++;
ctx.putImageData(canvasData, 0, 0);
if (pass < maxPass) {
timer = setTimeout(function() {
render();
}, 0);
}
}
render();
canvas.addEventListener('click', function(e) {
var x = e.clientX / scale + offset[0],
y = (height - e.clientY) / scale + offset[1];
scale *= 2;
offset[0] = -width / 2 / scale + x;
offset[1] = -height / 2 / scale + y;
pass = 0;
maxPass *= 2;
dalpha++;
ctx.clearRect(0, 0, width, height);
canvasData = ctx.getImageData(0, 0, width, height);
clearTimeout(timer);
render();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment