Source code for Javascript tree that features in “Inventing on Principle” video

后端 未结 3 1799
野性不改
野性不改 2020-12-28 22:04

I was quite inspired by Bret Victor\'s Inventing on Principle video (http://vimeo.com/36579366).

Also, I was very fascinated by that tree drawn using Javascript. I

相关标签:
3条回答
  • 2020-12-28 22:43

    Drawing a tree with the canvas is simple enough. See below for a solution in about 80 lines of code.

    Several people have started attempts at re-creating the interactive environment from the video. One of those attempts was made by github user tnlogy. His environment allows you to select a number in the code and change the running demo on-the-fly using a slider. I've forked his code to include a tree demo.

    Demo for interactive tree:

    http://brianpeiris.github.com/live-coding/

    Demo for simple tree:

    http://jsfiddle.net/brianpeiris/v9zD6/show

    Source for simple tree demo

    var
      drawLeaf = function (cx, xx, yy) {
        var
          leafAlpha = 8/10,
          leafSize = 7;
    
        cx.beginPath();
        cx.fillStyle = (
          "rgba(" + 
          Math.round(220 + (Math.random() * 50)) + ", " + 
          Math.round(180 + (Math.random() * 50)) + ", " + 
          Math.round(220 + (Math.random() * 50)) + ", " + 
          leafAlpha + 
          ")"
        );  
        cx.arc(xx, yy, leafSize, 0, Math.PI * 2);
        cx.fill();
      },
      drawBranch = function (ii, cx, xx, yy, level, levels, angle, numBranches) {
        var
          branchLength = 44,
          subBranchWidthFactor = 2,
          sweep = Math.PI * 25/30,
          branchTweakMagnitude = 52/50,
          tt;
    
        cx.beginPath();
    
        // Draw thinner branches away from the trunk
        cx.lineWidth = (levels - level) * subBranchWidthFactor;
    
        // Calculate the angle of the branch, with some random tweaks
        tt = (
          sweep * ii / (numBranches - 1) + angle -
          sweep / 2 + Math.PI + 
          Math.random() * 0.5 * branchTweakMagnitude
        );
    
        cx.moveTo(xx, yy);
        newXX = xx + Math.sin(tt) * branchLength;
        newYY = yy + Math.cos(tt) * branchLength;
        cx.lineTo(newXX, newYY);
        cx.stroke();
    
        // Recursively draw more branches
        drawBranchesAndLeaves(cx, newXX, newYY, level + 1, levels, Math.PI + tt);
      },
      drawBranchesAndLeaves = function (cx, xx, yy, level, levels, angle) {
        var
          numBranches = 5,
          ii, newXY;
    
        // This function is called recursively. The recursion terminates when we
        // have reached the specified number of recursive levels.
        if (level === levels) { 
          drawLeaf(cx, xx, yy);
          return; 
        }
        else {
          for (ii = 0; ii < numBranches; ii++) {
            drawBranch(ii, cx, xx, yy, level, levels, angle, numBranches);
          }
        }
      },
    
      drawTree = function(cx, ww, hh) {
        var trunkX = ww / 2, trunkY = hh - 165;
    
        cx.strokeStyle = "black";
        cx.lineWidth = 13;
        cx.lineCap = "round";
    
        cx.moveTo(trunkX, hh);
        cx.lineTo(trunkX, trunkY);
        cx.stroke();
    
        drawBranchesAndLeaves(cx, trunkX, trunkY, 0, 3, 0);
      },
      width = 350,
      height = 350,
      canvas = $('<canvas width="' + width + '" height="' + height + '"></canvas>'),
      ctx = canvas[0].getContext("2d");
    
      $('body').append(canvas);
      drawTree(ctx, width, height);
    
    0 讨论(0)
  • 2020-12-28 22:57

    Credit to Ian Johnson ( @enjalot ) for sharing this with me, but here is a link to d3js version of a tree. http://tributary.io/inlet/4b0a56692447fa75d8a1 which is adapted from this version by Peter Cook http://prcweb.co.uk/lab/d3-tree/

    Uses combo of paths:

    var pathGenerator = d3.svg.line()
    .x(function(d) {
      return d.x;
    })
    .y(function(d) {
      return d.y;
    })
    

    And functions that fetch parents, points and paths:

    function getPoints(branches) {
      var points = [];
      branches.forEach(function(branch) {
        points.push( {x: x1(branch), y: y1(branch) });
        points.push( {x: x2(branch), y: y2(branch) });
      });
      return points;
    }
    
    function getParent(branch, p, branches) {
      if(!branch.parent) return;
      var b = branches[branch.parent];
      p.push({x: b.x, y: b.y})
      getParent(b, p, branches);
    
    }
    
    
    function getPaths(branches) {
      var paths = [];
    
      var i = 0;
      branches.forEach(function(branch) {
        if(branch.d < maxDepth) return;
        var p = [{x: branch.x, y: branch.y}];
        getParent(branch, p, branches);
        p.push(seed);
        paths.push(p);
      });
      return paths;
    }
    

    Again, HT to Ian. Live demo here.

    0 讨论(0)
  • 2020-12-28 23:00

    This is a good place to start, if you are very new to 2D graphics in Javascript.

    https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas

    As for the tree source code, I would be interested in looking at it too!

    0 讨论(0)
提交回复
热议问题