Skip to content

Instantly share code, notes, and snippets.

@gchan
Created December 10, 2013 04:11
Show Gist options
  • Save gchan/7885615 to your computer and use it in GitHub Desktop.
Save gchan/7885615 to your computer and use it in GitHub Desktop.
Koch Snowflake (with HTML5 canvas)
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px sans-serif;
}
</style>
<body>
<div id='controls'>
<button id='subtract'>-</button>
<button id='add'>+</button>
Level <strong id='level'>4</strong>
</div>
<canvas id='canvas'></canvas>
<script>
var width = 400, height = 480;
var tan_sixty = Math.tan(Math.PI * 1 / 3);
var triangle_height = width / 2 * tan_sixty;
var root_triangle = [
{ x: width / 2, y: 0 },
{ x: 0, y: triangle_height },
{ x: width, y: triangle_height },
{ x: width / 2, y: 0 }
];
var data_cache = {
0: root_triangle
};
var level = 4;
var canvas = document.getElementById('canvas');
canvas.width = width;
canvas.height = height;
function clone_obj(obj) {
return JSON.parse(JSON.stringify(obj));
}
function koch_iteration(v0, v1) {
var base_vector = {
x: v1.x - v0.x,
y: v1.y - v0.y
};
var orthogonal_vector = {
x: v0.y - v1.y,
y: v1.x - v0.x
};
var left, right, top;
left = {
x: v0.x + base_vector.x / 3,
y: v0.y + base_vector.y / 3
};
right = {
x: v1.x - base_vector.x / 3,
y: v1.y - base_vector.y / 3
};
top = {
x: v0.x + base_vector.x / 2 + tan_sixty * orthogonal_vector.x / 6,
y: v0.y + base_vector.y / 2 + tan_sixty * orthogonal_vector.y / 6
};
return [ left, top, right ];
}
function compute_points(levels) {
var data, new_points;
var splice = Function.prototype.apply.bind(Array.prototype.splice);
if (data_cache[levels]) {
return data_cache[levels];
}
previous_data = compute_points(levels - 1);
data = clone_obj(previous_data);
previous_data.forEach(function(point, index, array) {
if (index + 1 >= array.length) {
return;
}
new_points = koch_iteration(point, array[index + 1]);
splice(data, [index * 4 + 1, 0].concat(new_points));
});
data_cache[levels] = data;
return data;
}
function render_koch_snowflake(levels) {
var ctx = canvas.getContext('2d'),
points;
if (!canvas.getContext) {
alert("You need a modern browser to view this demo.");
return;
}
points = compute_points(levels);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'steelblue';
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
points.forEach(function(point) {
ctx.lineTo(point.x, point.y);
});
ctx.stroke();
document.getElementById('level').innerHTML = level;
}
function increase_level() {
level = Math.min(level + 1, 7);
render_koch_snowflake(level);
}
function decrease_level() {
level = Math.max(level - 1, 0);
render_koch_snowflake(level);
}
document.getElementById('subtract').addEventListener('click', decrease_level);
document.getElementById('add').addEventListener('click', increase_level);
render_koch_snowflake(level);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment