Skip to content

Instantly share code, notes, and snippets.

@sarah37
Last active March 17, 2019 18:05
Show Gist options
  • Select an option

  • Save sarah37/2294a178ce140ff83ee8a200950aa6b0 to your computer and use it in GitHub Desktop.

Select an option

Save sarah37/2294a178ce140ff83ee8a200950aa6b0 to your computer and use it in GitHub Desktop.
Sierpinski II
height: 960
redirect: https://observablehq.com/@sarah37/sierpinski-triangles

Sierpinski triangle with canvas and d3, constructed by removing triangles. The method is the following:

  1. Start with an equilateral triangle.
  2. Subdivide it into four smaller congruent equilateral triangles and remove the central triangle.
  3. Repeat step 2 with each of the remaining smaller triangles forever.

The number of iterations is limited to 9 here due to the size of the canvas.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sierpinski</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://d3js.org/d3.v4.js"></script>
</head>
<body>
<div id="canvasDiv"></div>
<script type="text/javascript" src="sierpinski.js"></script>
</body>
</html>
var w = 960;
var h = 960;
var b = 20;
var c = d3.select("#canvasDiv")
.append("canvas")
.attr("width", w)
.attr("height", h);
var context = c.node().getContext("2d");
// initial (largest) triangle
var triangles = [[[w/2, h/2 - (Math.sqrt(3)*w/2 - b)/2], [b, h/2 + (Math.sqrt(3)*w/2 - b)/2], [w-b, h/2 + (Math.sqrt(3)*w/2 - b)/2]]];
// draw initial triangle
context.beginPath();
context.moveTo(triangles[0][0][0], triangles[0][0][1]);
context.lineTo(triangles[0][1][0], triangles[0][1][1]);
context.lineTo(triangles[0][2][0], triangles[0][2][1]);
context.fillStyle="#fff";
context.fill();
context.closePath();
// set iterations
var iter = 9;
var i = 0;
setTimeout(function(){ removeTriangles(triangles); }, 1000);
function removeTriangles(triangles) {
setTimeout(function() {
var newtriangles = [];
triangles.forEach(function(el, i) {
// "remove" triangle in the middle by painting over it
var nt = [halfway(el[1], el[2]),
halfway(el[2], el[0]),
halfway(el[0], el[1])]
context.beginPath();
context.moveTo(nt[0][0], nt[0][1]);
context.lineTo(nt[1][0], nt[1][1]);
context.lineTo(nt[2][0], nt[2][1]);
context.fillStyle="#000";
context.fill();
context.closePath();
// push new triangles to our array
newtriangles.push([nt[0], nt[1], el[2]],
[nt[0], el[1], nt[2]],
[el[0], nt[1], nt[2]])
})
i++
if (i < iter) {removeTriangles(newtriangles);}
}, 750)
}
function halfway(a,b) {
return [(a[0]+b[0]) / 2, (a[1]+b[1]) / 2]
}
body, html {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #000;
}
#counter {
position: absolute;
left: 10px;
top: 10px;
font-family: sans-serif;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment