block by curran 306a51423662f3a787dd99b4bbc62723

Tree Fractal with SVG (broken)

Full Screen

A tree fractal using SVG and D3 in a broken, incomplete state. This is what happens when you don’t use the exit() part of the enter/update/exit pattern.

See also the fully working version.

You can buy prints of this graphic (with 786,411 circles!).

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>fractal</title>
    <script src="https://d3js.org/d3.v4.min.js"></script>
  </head>
  <body>
    <svg width="960" height="500"></svg>
    <script>
      
      var svg = d3.select("svg"),
          width = svg.attr("width"),
          height = svg.attr("height"),
          nMax = 95,
          mouseX = 800, mouseY = 83,
          scaleFactor = (100 - 4.4688) / 100;
      
      function redraw (){
        var scale = 20,
            angle = -mouseY / height * Math.PI / 8,
            n = Math.floor(nMax * mouseX / 960),
            up = Math.PI,
            data = fractal(497, 472, up, scale, angle, 0, n, false);
        
        render(data);
      }
      
      function fractal(x, y, direction, scale, angle, i, n, flip){
        
        var circle = {
          x: x,
          y: y,
          radius: scale / 2
        };

        direction += angle;
        x += Math.sin(direction) * scale;
        y += Math.cos(direction) * scale;
        
        if(flip){
          angle = -angle;
        }
        
        if(i < n){
          return [circle]
            .concat(
              fractal(x, y, direction, scale * scaleFactor, angle, i+1, n, flip)
            )
            .concat(
              (i % 11 === 0)
              ? fractal(x, y, direction, scale * scaleFactor, angle, i+1, n, !flip)
              : []
            );
        } else {
          return [circle];
        }

      }
      
      function render(data){
        var circles = svg.selectAll("circle").data(data);
        circles
          .enter()
            .append("circle")
          .merge(circles)
            .attr("cx", function (d){ return d.x; })
            .attr("cy", function (d){ return d.y; })
            .attr("r", function (d){ return d.radius; })
        
        
      }
      
      redraw();
      document.addEventListener("mousemove",function(e){
        mouseX = e.x;
        mouseY = e.y;
        redraw();
      });
    </script>
  </body>
</html>