【问题标题】:Change tree graph based on select input value根据选择输入值更改树形图
【发布时间】:2022-10-23 20:22:13
【问题描述】:

我试图让我的树形图根据输入中选择的值做出响应。我让它适用于第一个选择,但是当我再次将选择放回“全部”时没有任何反应。

我在控制台中收到以下错误:

我想这是因为在进行选择时,一些孩子被删除了,因此在将其放在完整选择中时不再找到,但我不确定如何解决这个问题。

codepen

图的代码:

//Load data
const data = [
  {
    "name": "Top Level",
    "parent": "null",
    "value": 10,
    "type": "black",
    "level": "red",
    "children": [
      {
        "name": "Level 2A",
        "parent": "Top Level",
        "value": 15,
        "type": "grey",
        "level": "red",
        "children": [
          {
            "name": "Son of A",
            "parent": "Level 2: A",
            "value": 5,
            "type": "steelblue",
            "level": "orange"
          },
          {
            "name": "Daughter of A",
            "parent": "Level 2: A",
            "value": 8,
            "type": "steelblue",
            "level": "red"
          }
        ]
      },
      {
        "name": "Level 2B",
        "parent": "Top Level",
        "value": 10,
        "type": "grey",
        "level": "green"
      }
    ]
  }
];

var margin = {top: 10, right: 10, bottom: 10, left: 50},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;

var tree = d3.cluster()
    .size([height, width])
    .size([height-margin.top-margin.bottom,width-margin.left-margin.right]); 

//Create root 
var root = d3.hierarchy(data[0], function(d) { return d.children;});

//Attach canvas element
var svg = d3.select("body")
            .append("svg")
            .attr("width", 1000)
            .attr("height", 1000);  
    
var g = svg
        .append("g")
        .attr('transform','translate('+ margin.left +','+ margin.right +')');

var link = g.selectAll(".link")
        .data(tree(root).links())
        .enter()
        .append("path")
        .attr("class", "link")
        .attr("d", d3.linkHorizontal()
                .x(function(d) {return d.y;})
                .y(function(d) {return d.x;}));      
 
var node = g.selectAll(".node")
        .data(root.descendants())
        .enter()
        .append("g") 
        .attr("class", "link") 
        .attr("class", d => 
        { return "node" + (d.children ? " node--internal" : " node--leaf")})
        .attr("transform", d => 
        { return "translate(" + d.y + ","+ d.x + ")" ; })
    
var text = g.selectAll("text")
        .data(root.descendants())
        .enter().append("text")
        .text(d => d.data.name)
        .attr("class", "label glow") 
        .attr('text-anchor', "start")
        .attr("x", d => d.y)
        .attr("y", d => d.x);

circle = node.append("circle")
    .attr("r", 2.5)

//Select
    var selections = ["All", "Level 2A", "Level 2B"]

    d3.select("#selectButton")
      .selectAll('myOptions')
      .data(selections)
      .enter()
      .append('option')
      .text(function (d) { return d; }) // 
      .attr("value", function (d) { return d; })  

  // SelectInput
  d3.select("#selectButton").on("change", function(d){
    selectedGroup = this.value
    updateChart(selectedGroup, data)
  })

//Update chart function
function updateChart(selection, data){
  
  //Filter data
  if(selection != "All"){
    var selData = data[0].children.filter(d => d.name == selection);
  } else {
    var selData = data
  }
  console.log(selData)
  var root = d3.hierarchy(selData[0], function(d) { return d.children;}); 
  console.log(root)
  
  //update chart
  link
    .data(tree(root).links())
    .join()
    .transition()
    .duration(1000)
    .attr("class", "link")
    .attr("d", d3.linkHorizontal()
          .x(function(d) {return d.y;})
          .y(function(d) {return d.x;})
         );
   text
    .data(root.descendants())
    .join()
    .transition()
    .duration(1000)
        .attr('text-anchor', "start")
        .attr("x", d => d.y)
        .attr("y", d => d.x);
   node
    .data(root.descendants())
    .join()
    .transition()
    .duration(1000)
        .attr("class", "link") 
        .attr("class", d => 
        { return "node" + (d.children ? " node--internal" : " node--leaf")})
        .attr("transform", d => 
        { return "translate(" + d.y + ","+ d.x + ")" ; })
  circle
     .data(root.descendants())
     .join()
     .transition()
     .duration(1000)
     .attr("r", 2.5)
};

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    回答我自己的问题。我必须在enter()update()exit() 上设置确切需要发生的事情。

    我从刚加入改变:

      link
        .data(tree(root).links())
        .join()
        .transition()
        .duration(1000)
        .attr("class", "link")
        .attr("d", d3.linkHorizontal()
              .x(function(d) {return d.y;})
              .y(function(d) {return d.x;})
             );
    

    至:

      var link = g
        .selectAll(".link")
        .data(tree(root).links())
        .join(
          (enter) =>
            enter
              .append("path")
              .attr("class", "link")
              .attr(
                "d",
                d3
                  .linkHorizontal()
                  .x(function (d) {
                    return d.y;
                  })
                  .y(function (d) {
                    return d.x;
                  })
              ),
          (update) =>
            update
              .transition()
              .duration(1000)
              .attr("class", "link")
              .attr(
                "d",
                d3
                  .linkHorizontal()
                  .x(function (d) {
                    return d.y;
                  })
                  .y(function (d) {
                    return d.x;
                  })
              ),
          (exit) => exit.remove()
        );
    
    

    有关完整的工作树,请参见:

    https://codepen.io/nvelden/pen/jOxgoVj

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 2014-05-03
      • 2013-09-27
      • 2014-02-25
      • 1970-01-01
      相关资源
      最近更新 更多