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; | |
| } |