Working towards a Hilbert Curve based grid layout
LSystem code lifted from this block by nitaku who has many fascinating d3 experiments
TODO: more pointAlongPath blocks.
Built with blockbuilder.org
Working towards a Hilbert Curve based grid layout
LSystem code lifted from this block by nitaku who has many fascinating d3 experiments
TODO: more pointAlongPath blocks.
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
<script src="lsystem.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
svg { width: 100%; height: 100%; } | |
.curve { | |
fill: none; | |
stroke: #b5b5b5; | |
} | |
</style> | |
</head> | |
<body> | |
<svg></svg> | |
<script> | |
var side = 20; | |
var revealDuration = 500; | |
var revealOffset = 150; | |
var steps = 4 | |
var hilbertConfig = { | |
steps: steps, | |
axiom: 'A', | |
rules: { | |
A: '-BF+AFA+FB-', | |
B: '+AF-BFB-FA+' | |
} | |
} | |
var test = LSystem.fractalize(hilbertConfig); | |
var angle = -Math.PI / 2; | |
var testCurve = LSystem.path({ | |
fractal: test, | |
side: side, | |
angle: angle, | |
}) | |
var testGrid = LSystem.grid({ | |
fractal: test, | |
side: side, | |
angle: angle | |
}) | |
var color = d3.scale.linear() | |
.domain([0, testGrid.length]) | |
.range(["#65a0ff", "#cc4e00"]) | |
.interpolate(d3.interpolateHcl) | |
var svg = d3.select("svg") | |
var g = svg.append("g") | |
.attr("transform", "translate(330, 40)") | |
var duration = testGrid.length * revealOffset; | |
g.append("path").classed("curve", true) | |
.attr({ | |
d: testCurve, | |
"stroke-dasharray": function() { | |
var tracklength = this.getTotalLength(); | |
return tracklength + " " + tracklength; | |
}, | |
"stroke-dashoffset": function() { | |
return this.getTotalLength(); | |
}, | |
}) | |
.transition() | |
.duration(duration).delay(revealDuration/2) | |
.ease("linear") | |
.attrTween("stroke-dashoffset", revealAlong) | |
g.selectAll("circle.point") | |
.data(testGrid) | |
.enter() | |
.append("circle").classed("point", true) | |
.attr({ | |
cx: function(d,i) { return d.x }, | |
cy: function(d,i) { return d.y }, | |
r: 4, | |
fill: function(d,i) { return color(d.j) }, | |
opacity: 0, | |
}) | |
.transition().duration(revealDuration) | |
.delay(function(d) { return d.j * revealOffset }) | |
.attr({ | |
opacity: 1 | |
}) | |
function revealAlong(d, i, a) { | |
var l = this.getTotalLength(); | |
return function(t) { | |
if(t > 1) { t = 1} | |
return l * (1-t); | |
}; | |
}; | |
</script> | |
</body> |
// from http://bl.ocks.org/nitaku/8947871 | |
var LSystem = window.LSystem = {} | |
LSystem.fractalize = function(config) { | |
var char, i, input, output, _i, _len, _ref; | |
input = config.axiom; | |
for (i = 0, _ref = config.steps; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) { | |
output = ''; | |
for (_i = 0, _len = input.length; _i < _len; _i++) { | |
char = input[_i]; | |
if (char in config.rules) { | |
output += config.rules[char]; | |
} else { | |
output += char; | |
} | |
} | |
input = output; | |
} | |
return output; | |
}; | |
/* convert a Lindenmayer string into an SVG path string | |
*/ | |
LSystem.path = function(config) { | |
var angle, char, path, _i, _len, _ref; | |
angle = 0.0; | |
path = 'M0 0'; | |
_ref = config.fractal; | |
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
char = _ref[_i]; | |
if (char === '+') { | |
angle += config.angle; | |
} else if (char === '-') { | |
angle -= config.angle; | |
} else if (char === 'F') { | |
path += "l" + (config.side * Math.cos(angle)) + " " + (config.side * Math.sin(angle)); | |
} | |
} | |
return path; | |
}; | |
LSystem.grid = function(config) { | |
var angle, char, i, j, len, ref, x, y; | |
angle = 0.0; | |
j = 1; | |
var grid = [{x: 0, y: 0, j: 0}]; | |
ref = config.fractal; | |
for (i = 0, len = ref.length; i < len; i++) { | |
//if(j >= config.data.length) return grid; | |
char = ref[i]; | |
if (char === '+') { | |
angle += config.angle; | |
} else if (char === '-') { | |
angle -= config.angle; | |
} else if (char === 'F') { | |
x = config.side * Math.cos(angle); | |
y = config.side * Math.sin(angle); | |
x += grid[j-1].x; | |
y += grid[j-1].y; | |
grid.push({ | |
x: x, | |
y: y, | |
//data: config.data[j], | |
j: j | |
}); | |
j++ | |
} | |
} | |
return grid; | |
} |