Last active
August 19, 2016 01:36
-
-
Save treboresque/28476a3ae1297af52d95 to your computer and use it in GitHub Desktop.
Sierpinski Charlet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html > | |
<head> | |
<title>Sierpinski</title> | |
<link rel="stylesheet" href="./style.css"> | |
</head> | |
<body> | |
<div class="chart"></div> | |
</body> | |
<script src="http://d3js.org/d3.v3.min.js" type="text/javascript"></script> | |
<script src="https://rawgit.com/twitter/d3kit/v0.1.0/dist/d3kit.min.js" type="text/javascript"></script> | |
<script src="main.js" type="text/javascript"></script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var DEFAULT_OPTIONS = { | |
margin: {top: 20, right: 20, bottom: 20, left: 20} | |
}; | |
// create sierpinski | |
var sierpinski = new Sierpinski(6); | |
var chart = new d3Kit.Skeleton('.chart', DEFAULT_OPTIONS) | |
.autoResize('both') | |
.on('resize', onResize); | |
var options = chart.options(); | |
// add sierpinski to | |
chart.getRootG() | |
.call(sierpinski.enter); | |
// handle resize | |
function onResize() { | |
var width = chart.getInnerWidth (); | |
var height = chart.getInnerHeight(); | |
var center = [options.margin.left + width / 2, options.margin.top + height / 2]; | |
sierpinski.property('edgeLength', d3.min([width, height])); | |
chart.getRootG() | |
.attr('transform', 'translate(' + center + ')') | |
.call(sierpinski.update); | |
} | |
// sierpinski chartlet | |
function Sierpinski(depth, color) { | |
// constants | |
var ANGLES = d3.range(0, 360, 120).map(function(d) {return degreesToRadians(d + 30);}); | |
var TRIANGLE = 'M P0 L P1 L P2 z'; | |
var EDGE_RADIUS_RATIO = Math.sqrt(3) / 3; | |
color = color || [255, 128, 128]; | |
var events = []; | |
var children = depth > 0 ? new Sierpinski(depth - 1) : null; | |
var charlet = d3Kit.Chartlet(enter, update, exit, events); | |
function enter(selection, onEnd) { | |
// if bottom out on depth, actually add path to plot triangles | |
if (depth == 0) { | |
selection | |
.append('path') | |
.classed('triangle', true) | |
.attr('d', function() { | |
return createTrianglePath(0); | |
}) | |
.style('fill', triangleColor); | |
} | |
// otherwise add children | |
else { | |
// create 3 groups one for each child sierpinski triangle | |
var groups = selection.selectAll('g.child') | |
.data(ANGLES) | |
.enter() | |
.append('g') | |
.classed('child', true) | |
.attr('transform', 'translate(0, 0)'); | |
groups.call(children.enter); | |
} | |
onEnd(); | |
} | |
function update(selection, onEnd) { | |
var radius = charlet.getPropertyValue('edgeLength') * EDGE_RADIUS_RATIO; | |
// if children, update those | |
if (children) { | |
// update done when children update is done | |
children.on('updateDone', onEnd); | |
selection.selectAll('g.child') | |
.transition() | |
.attr('transform', function(d) { | |
var x = Math.cos(d) * radius / 2; | |
var y = Math.sin(d) * radius / 2 + radius / 8; | |
return 'translate(' + x + ', ' + y + ')'; | |
}); | |
children.property('edgeLength', charlet.getPropertyValue('edgeLength') / 2); | |
selection.selectAll('g.child') | |
.call(children.update); | |
} | |
// otherwise update the triangle | |
else { | |
selection.selectAll('path.triangle') | |
.transition() | |
.attr('d', function() { | |
return createTrianglePath(radius); | |
}) | |
.each('end', onEnd); | |
} | |
} | |
function exit(selection, onEnd) { | |
onEnd(); | |
} | |
function triangleColor(d, i) { | |
var localColor = color.map(function(_d, _i) {return i != _i ? _d * .7 : _d;}); | |
return d3.rgb(localColor[0], localColor[1], localColor[2]); | |
}; | |
// join a pattern and a set of x,y points | |
function pathPoints(pattern, points) { | |
return points.reduce(function(acc, point, i) { | |
return acc.replace('P' + i, point.x + ' ' + point.y); | |
}, pattern); | |
} | |
// convert degrees to radians | |
function degreesToRadians(degrees) { | |
return degrees / 180 * Math.PI; | |
} | |
// given a radius, create a triangel around the origin | |
function createTrianglePath(radius) { | |
var points = ANGLES.map(function(angle) { | |
return { | |
x: Math.cos(angle) * radius, | |
y: Math.sin(angle) * radius + radius / 4, | |
}; | |
}); | |
return pathPoints(TRIANGLE, points); | |
} | |
return charlet; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html { | |
margin: 0px; | |
padding: 0px; | |
width: 100%; | |
height: 100%; | |
} | |
body { | |
margin: 0px; | |
padding: 0px; | |
width: 100%; | |
height: 100%; | |
} | |
.chart { | |
width: 100%; | |
height: 100%; | |
} | |
path { | |
stroke: #888; | |
stroke-width: 1px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment