首页 > 解决方案 > d3.js - 显示带有 d3 堆栈溢出的树节点

问题描述

下面的代码尝试显示由 d3.tree 和 d3.js 创建的节点。会导致栈溢出。我添加了一个总变量以在 10 个循环后停止循环!

这可能是由于某些标准对象已在循环中迭代但不知道如何跳过这些节点!

console.clear()
tree_v6_test()
function tree_v6_test() {
  var treeData = {
    name: "A",
    children: [
      { 
        name: "B",
        children: [
          { name: "C" },
          { name: "D" }
        ]
      },
      { name: "E"}
    ]
  };

  var treemap = d3.tree().size([200, 100]);
  var nodes = d3.hierarchy(treeData);
  show(nodes,1,600,1200)
}

function isDict(v) {
  return typeof v==='object' && v!==null && !(v instanceof Array) && !(v instanceof Date);
}

function mytree(indata) {
  var total = 0
  function utils(v) {
    total++
    if (total > 20) return '?';

    var children = []
    if (v instanceof Array) {
      v.map(d => {
        var name = Object.keys({d})[0]
        if (isDict(d)) name = 'dict'
        if (!(d instanceof Array) && !isDict(d)) {       
          children.push({name:name})
        }else{
          var obj = utils(d)
          children.push({name:name,children:obj})
        }
      })
    }else if (isDict(v)) {
      for (var d in v){

        if (!(v[d] instanceof Array) && !isDict(v[d])) {

          children.push({name:d +":" + v[d]})
        }else{
          var obj = utils(v[d])
          children.push({name:d,children:obj})
        }
      }
    }else{
      return {name:v};
    }
    return children
  }

  var name = Object.keys({indata})[0]
  try{
    children = utils(indata)
  }catch(e) {
    console.log(total)
    return []
  }
  treeData = {
    name:name,
    children:children
  }
  return treeData
}

function show(data,dir=1,w=800,h=1200) {
  var treeData = mytree(data)
  var margin = {top: 40, right: 90, bottom: 50, left: 90},
      width = w - margin.left - margin.right,
      height = h - margin.top - margin.bottom;

  if (dir == 1) {
    var treemap = d3.tree().size([height, width]);
  }else{
    var treemap = d3.tree().size([width, height]);
  }

  var nodes = d3.hierarchy(treeData);
  nodes = treemap(nodes);
  var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)

  var g = svg.append("g")
  .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

  g.append('rect')
    .attr('x',0)
    .attr('y',0)
    .attr('width',w)
    .attr('height',h)
    .attr('fill','none')
    .attr('stroke','red')

  var link = g.selectAll(".link")
  .data(nodes.descendants().slice(1))
  .enter().append("path")
  .attr("class", "link")
  .attr("d", d => diagonal(d))
  .attr('fill','none')
  .attr('stroke','#ccc')
  .attr('stroke-width',2)

  var node = g.selectAll(".node")
  .data(nodes.descendants())
  .enter().append("g")
  .attr("class", function(d) { 
    var thz = d3.select(this)
    if (d.children) {
      thz.attr('font-size',14)
      thz.attr('text-shadow','0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff')
    }else{
      thz.attr('font-size',14)
      thz.attr('font','sans-serif')
    }
    return "node" + 
      (d.children ? " node--internal" : " node--leaf"); })
  .attr("transform", function(d) { 
    if (dir == 0) {
      return "translate(" + d.x + "," + d.y + ")";
    }else{
      return "translate(" + d.y + "," + d.x + ")";
    }
  });

  node.append("circle")
    .attr("r", 1)
    .attr('fill','#fff')
    .attr('stroke','steelblue')
    .attr('stroke-width',3)

  node.append("text")
    .attr("dx", ".35em")
    .attr("x", function(d) { return d.children ? -20 : 20; })
    .style("text-anchor", "middle")
    .text(function(d) {return d.data.name; })

  function diagonal(d) {
    var sx = d.x
    var sy = d.y
    var tx = d.parent.x
    var ty = d.parent.y
    if (dir == 1) {//horizontal
      return ['M',sy,sx,'C',(sy+ty)/2,sx,(sy+ty)/2,tx,ty,tx].join(' ');
    }else{//vertical
      return ['M',sx,sy,'C',sx,(sy + ty) / 2,tx,(sy + ty) / 2,tx,ty].join(' ');
    } 
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

标签: d3.js

解决方案


推荐阅读