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

后端 未结 3 1798
野性不改
野性不改 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 = $(''),
      ctx = canvas[0].getContext("2d");
    
      $('body').append(canvas);
      drawTree(ctx, width, height);
    

提交回复
热议问题