使用 js canvas 画一棵二叉树

使用 js canvas 画一棵二叉树

闲话少说,上效果图

在这里插入图片描述

页面执行时是一层一层画出来的,下面是代码,优化的空间很大,有兴趣的可以拿去搞一搞


  var Point = function(x, y){
    
    
    this.x = x;
    this.y = y;
  };

  var Line = function(length, startPoint, endPoint, direction, lr){
    
    
    this.length = length;
    this.startPoint = startPoint;
    this.endPoint = endPoint;
    this.lr = lr;//用来区别根以上的分支是左还是右
    this.direction = direction;
  };

  function printLine(l){
    
    
    ctx.fillStyle="#eaeaea";
    ctx.fillRect(0,0,1440,860);
    ctx.moveTo(l.startPoint.x, l.startPoint.y);
    ctx.lineTo(l.endPoint.x, l.endPoint.y);
    ctx.strokeStyle="#1ee9a9";
    ctx.stroke();
  }

  //默认值:角度步长、起点、线段长度、初始方向、等级;角度步长、0级起点位置,作为不变信息处理
  var angle = 18; 
  var startPoint = new Point(720, 860);
  var level = 0;

  var length = 60;
  var direction = 0;
  var lineArr = [];

  function getEndPoint(startP, len, ang, flag){
    
    
    var x = Math.sin(2 * Math.PI / 360 * ang) * len;
    var y = Math.cos(2 * Math.PI / 360 * ang) * len;
    return new Point(startP.x + flag * x, startP.y - y);
  }

  //flag 取值 “-1”“1”,表示当前线条在那个大分支上,-1左分支,1右分支
  //n 表示当前计算的线是左分支=1、右分支=-1
  function getLine(len, newSP, n, dir, flag){
    
    
    var ang = dir + n * angle;
    return new Line(len, newSP, getEndPoint(newSP, len, ang, flag), ang, flag);
  }

  function getRootEndPoint(sp, len){
    
    
    var ang = 0;
    var x = Math.sin(2 * Math.PI / 360 * ang) * len;
    var y = Math.cos(2 * Math.PI / 360 * ang) * len;
    return new Point(sp.x - x, sp.y - y);
  }
  function getRootLine(len, sp, dir, lr){
    
    
    return new Line(len, sp, getRootEndPoint(startPoint, length), dir, lr);
  }

  function init(){
    
    
    console.log("level = " + level);
    if(level == 0){
    
    
      lineArr[0] = getRootLine(length, startPoint, direction, "root");
    }else{
    
    
      var n = Math.pow(2, level - 1);//当前的根节点是几个
      var arr = [];//取出来的根节点
      //通过 lineArr 倒叙 取
      for(var i = 0 ; i < n ; i ++){
    
    
        arr[arr.length] = lineArr[lineArr.length - 1 - i];
      }
      //根据 arr 计算新节点,每个节点可算出两个新节点
      var resArr = [];
      for(var i = 0 ; i < arr.length ; i ++){
    
    
        var oneLine = arr[i];
        var lr = oneLine.lr;
        var newSP = oneLine.endPoint;
        var len = oneLine.length - 2;
        var dir = oneLine.direction;
        if("root" == lr){
    
    
          resArr[resArr.length] = getLine(len, newSP, 1, dir, -1);
          resArr[resArr.length] = getLine(len, newSP, 1, dir, 1);
        }else if("-1" == lr){
    
    
          resArr[resArr.length] = getLine(len, newSP, 1, dir, -1);
          resArr[resArr.length] = getLine(len, newSP, -1, dir, -1);
        }else{
    
    
          resArr[resArr.length] = getLine(len, newSP, 1, dir, 1);
          resArr[resArr.length] = getLine(len, newSP, -1, dir, 1);
        }
        
      }
      for(var i = 0 ; i < resArr.length ; i ++){
    
    

        var oneLine = resArr[i];
        lineArr[lineArr.length] = oneLine;
      }

    }
    level ++;//改变level
  }

  function printLineArr(){
    
    
    if(lineArr.length > 0){
    
    
      for(var i = 0 ; i < lineArr.length ; i ++){
    
    
        printLine(lineArr[i]);
      }
    }
  }
  var times = 0;
  function run(){
    
    
    ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
    times ++;
    if(times >= 100){
    
    
      times = 0;
      //变化的内容 level 、length 、起点终点坐标替换
      if(level < 10){
    
    
        init();
      }
    }
    printLineArr();
  }
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
window.requestAnimFrame = (function(){
    
    
    return  window.requestAnimationFrame       || 
            window.webkitRequestAnimationFrame || 
            window.mozRequestAnimationFrame    || 
            window.oRequestAnimationFrame      || 
            window.msRequestAnimationFrame     || 
            function(callback) {
    
    
               window.setTimeout(callback, 16);//16毫秒
//eval(callback);
            };
})();
(function animloop(){
    
    
    requestAnimFrame(animloop);
    run();
})();

猜你喜欢

转载自blog.csdn.net/u013276512/article/details/107106043