树状图js的实现方法

2021-01-19 23:14:24 浏览数 (1)

本文是基于决策树的需求做的前期demo实现,所以以二叉树为实现目标。基本术语如下:

二叉树

  • 1、二叉树中的节点最多只能有两个子节点,一左一右。因此不怒在度大于2的节点
  • 2、左右子节点的顺序不能颠倒
代码语言:txt复制
<body>
  <canvas id="canvas"></canvas>
  <button class="btn" onClick="draw()">画树</button>

  <script>
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var startX = window.innerWidth * 0.5;
    var startY = window.innerHeight;

    function init() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      ctx.fillStyle = 'rgb(255,255,255)';
      ctx.beginPath();
      ctx.moveTo(startX, startY * 0.9);
      ctx.lineTo(startX, startY * 0.7);
      ctx.closePath();
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 10;
      ctx.stroke();
    }

    function nextStep(parentLength, lineWidth, color, parentEndX, parentEndY, k, baseAngle, angle) {
      if (parentLength <= 1) {
        return 0;
      }
      var leftAngle = angle   baseAngle;
      var rightAngle = baseAngle - angle;
      //根据传来的角度,算出左枝和右枝需要偏移的量
      var LdisX = k * parentLength * Math.round(Math.cos(leftAngle / 180 * Math.PI) * 10) / 10;
      var LdisY = k * parentLength * Math.round(Math.sin(leftAngle / 180 * Math.PI) * 10) / 10;
      var RdisX = k * parentLength * Math.round(Math.cos(rightAngle / 180 * Math.PI) * 10) / 10;
      var RdisY = k * parentLength * Math.round(Math.sin(rightAngle / 180 * Math.PI) * 10) / 10;
      //算出左枝和右枝终点坐标的值
      var LXbough = parentEndX   LdisX;
      var LYbough = parentEndY - LdisY;
      var RXbough = parentEndX   RdisX;
      var RYbough = parentEndY - RdisY;
      //开始绘画
      ctx.beginPath();
      ctx.moveTo(parentEndX, parentEndY);
      ctx.lineTo(LXbough, LYbough);
      ctx.moveTo(parentEndX, parentEndY);
      ctx.lineTo(RXbough, RYbough);
      ctx.closePath();
      //当树枝长度到一定值时,树枝的颜色逐渐变浅
      var rgb = '#f'   color   ""   color;
      if (parentLength < 20) {
        ctx.strokeStyle = rgb;
        switch (color) {
          case 1: color = 4; break;
          case 4: color = 7; break;
          case 7: color = 'a'; break;
          case 'a': color = 'c'; break;
          case 'c': color = 'e'; break;
          default: color = 'e'; break;
        }
      } else {
        ctx.strokeStyle = 'black';
      }
      ctx.lineWidth = lineWidth;
      ctx.stroke();

      //树枝下个分支点的角度 值越大,伞盖越大,常数为了防止树枝分叉角度太小重叠
      var newAngle = Math.random() * 30   10;
      //画左枝和右枝
      nextStep(parentLength * k, lineWidth * 0.6, color, LXbough, LYbough, k, leftAngle, newAngle);
      nextStep(parentLength * k, lineWidth * 0.6, color, RXbough, RYbough, k, rightAngle, newAngle);
    }

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      init();
      nextStep(startY * 0.3, 6, 4, startX, startY * 0.7, 0.7, 90, Math.random() * 30   10);
    }

    init();

  </script>
</body>

效果图如下:

0 人点赞