/* compute a Lindenmayer system given an axiom, a number of steps and rules */ (function() { var curve, d, fractalize, height, svg, svg_path, transition, tweenDash, width; 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 */ svg_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; }; curve = fractalize({ axiom: '-L', steps: 4, rules: { L: 'LF+RFR+FL-F-LFLFL-FRFR+', R: '-LFLF+RFRFR+F+RF-LFL-FR' } }); d = svg_path({ fractal: curve, side: 6, angle: Math.PI / 2 }); width = 960; height = 500; svg = d3.select('body').append('svg').attr('width', width).attr('height', height); svg.append('path').attr('class', 'curve shadow').attr('d', d).attr('transform', 'translate(240,490)'); /* animate the path */ /* from Mike Bostock's stroke dash interpolation example http://bl.ocks.org/mbostock/5649592 */ tweenDash = function() { var i, l; l = this.getTotalLength(); i = d3.interpolateString('0,' + l, l + ',' + l); return function(t) { return i(t); }; }; transition = function(path) { return path.transition().duration(20000).attrTween('stroke-dasharray', tweenDash); }; svg.append('path').attr('class', 'curve').attr('d', d).attr('transform', 'translate(240,490)').call(transition); }).call(this);