简体   繁体   English

在树状图中输入、更新和退出选择

[英]Enter, update and exit selections in a treemap

I have a D3 v5 treemap that I show three levels of the hierarchy via a filter.我有一个 D3 v5 树状图,我通过过滤器显示层次结构的三个级别。 Showing all levels at once would make the map too busy.一次显示所有级别会使地图太忙。 I'd like to employ a drill down or drill up feature such that when you click on a given rect (either child or parent) that re-sets that rect as the root node and then displays another three levels of the hierarchy from that new root node.我想使用向下钻取或向上钻取功能,这样当您单击给定的 rect(子项或父项)时,该 rect 将该 rect 重新设置为根节点,然后显示该新层次结构的另外三个级别根节点。

I think I'm getting the new root node data, but I can't seem to get the map to update correctly with the onclick (the console.log in the exit().remove() doesn't get called after the onclick).我想我正在获取新的根节点数据,但我似乎无法使用onclick使地图正确更新( exit().remove()中的 console.log 在 onclick 后不会被调用)。 It seems like elements are not exiting correctly, or not getting to the exit().remove() .元素似乎没有正确退出,或者没有到达exit().remove()

Here is the code:这是代码:

const treemapLayout = d3.treemap()
  .size([1200, 700])
  .paddingOuter(16);

d3.json("test.json").then(function(data) {

  // update the view
  const update = (d) => {
  //console.log(d)

  let rootNode = d3.hierarchy(d)

  console.log(rootNode)

  rootNode
    .sum(function(d) { return d.value; })
    .sort(function(a, b) { return b.height - a.height || b.value - a.value; });

  treemapLayout(rootNode);


  let nodes = d3.select('svg g')
    .selectAll('g')
    .data(rootNode.descendants())

  nodes
    .enter()
    .filter(function(d) {
      return d.depth < 3;
    })
    .append('g')
    .merge(nodes)
    .attr('transform', function(d) {return 'translate(' + [d.x0, d.y0] + ')'})



  //nodes
    .append('rect')
    .attr('width', function(d) { return d.x1 - d.x0; })
    .attr('height', function(d) { return d.y1 - d.y0; })
    .attr('style', function(d) {
      return ('fill:' + d3.interpolateRdYlGn(d.data.health))
    })
    .on('click', function(d.parent) { console.log(d.data.name); update(d); })

  nodes
    .append('text')
    .attr('dx', 4)
    .attr('dy', 14)
    .text(function(d) {
      return d.data.name;
    })


  nodes
    .attr('style', function(d) { console.log('here'); return d; })
    .exit().remove()
  };

  update(data);
});

Here is the data in a simplified format:以下是简化格式的数据:

{
  "name": "A1",
  "health": 0.521,
  "children": [
    {
      "name": "B1",
      "health": 0.521,
      "children": [
        {
          "name": "B1-C1",
          "health": 0.614,
          "children": [
            {
              "name": "B1-C1-D1",
              "health": 0.666,
              "children": [
                {
                  "name": "B1-C1-D1-E1",
                  "value": 30,
                  "health": 0.8
                },
                {
                  "name": "B1-C1-D1-E2",
                  "value": 35,
                  "health": 0.5
                },
                {
                  "name": "B1-C1-D1-E3",
                  "value": 20,
                  "health": 0.7
                }
              ]
            },
            {
              "name": "B1-C1-D2",
              "health": 0.45,
              "children": [
                {
                  "name": "B1-C1-D2-E1",
                  "value": 10,
                  "health": 0.8
                },
                {
                  "name": "B1-C1-D2-E1",
                  "value": 14,
                  "health": 0.1
                }
              ]
            },
            {
              "name": "B1-C1-D3",
              "health": 0.64,
              "children": [
                {
                  "name": "B1-C1-D3-E1",
                  "value": 10,
                  "health": 0.8
                },
                {
                  "name": "B1-C1-D3-E2",
                  "value": 14,
                  "health": 0.2
                },
                {
                  "name": "B1-C1-D3-E3",
                  "value": 7,
                  "health": 0.7
                },
                {
                  "name": "B1-C1-D3-E4",
                  "value": 9,
                  "health": 0.9
                },
                {
                  "name": "B1-C1-D3-E5",
                  "value": 5,
                  "health": 0.6
                }
              ]
            },
            {
              "name": "B1-C1-D4",
              "value": 2,
              "health": 0.7
            }
          ]
        },
        {
          "name": "B1-C2",
          "health": 0.45,
          "children": [
            {
              "name": "B1-C2-D1",
              "health": 0.45,
              "value": 12
            }
          ]
        },
        {
          "name": "B1-C3",
          "health": 0.5,
          "children": [
            {
              "name": "B1-C3-D1",
              "health": 0.5,
              "value": 10
            }
          ]
        }
      ]
    }
  ]
}

D3 selections are immutable . D3 选择是不可变的

When you do this...当你这样做...

nodes.enter()
    .filter(function(d) {
      return d.depth < 3;
    })
    .append('g')
    .merge(nodes)
    //etc...

... the merge is not changing what nodes is, which is just the update selection. ... merge不会改变nodes是什么,这只是更新选择。

You have to reassign it:您必须重新分配它:

nodes = nodes.enter()
    //etc...

Here is your code with that change (in a smaller SVG):这是带有该更改的代码(在较小的 SVG 中):

 const data = { "name": "A1", "health": 0.521, "children": [{ "name": "B1", "health": 0.521, "children": [{ "name": "B1-C1", "health": 0.614, "children": [{ "name": "B1-C1-D1", "health": 0.666, "children": [{ "name": "B1-C1-D1-E1", "value": 30, "health": 0.8 }, { "name": "B1-C1-D1-E2", "value": 35, "health": 0.5 }, { "name": "B1-C1-D1-E3", "value": 20, "health": 0.7 } ] }, { "name": "B1-C1-D2", "health": 0.45, "children": [{ "name": "B1-C1-D2-E1", "value": 10, "health": 0.8 }, { "name": "B1-C1-D2-E1", "value": 14, "health": 0.1 } ] }, { "name": "B1-C1-D3", "health": 0.64, "children": [{ "name": "B1-C1-D3-E1", "value": 10, "health": 0.8 }, { "name": "B1-C1-D3-E2", "value": 14, "health": 0.2 }, { "name": "B1-C1-D3-E3", "value": 7, "health": 0.7 }, { "name": "B1-C1-D3-E4", "value": 9, "health": 0.9 }, { "name": "B1-C1-D3-E5", "value": 5, "health": 0.6 } ] }, { "name": "B1-C1-D4", "value": 2, "health": 0.7 } ] }, { "name": "B1-C2", "health": 0.45, "children": [{ "name": "B1-C2-D1", "health": 0.45, "value": 12 }] }, { "name": "B1-C3", "health": 0.5, "children": [{ "name": "B1-C3-D1", "health": 0.5, "value": 10 }] } ] }] } const treemapLayout = d3.treemap() .size([500, 300]) .paddingOuter(16); // update the view const update = (d) => { //console.log(d) let rootNode = d3.hierarchy(d) console.log(rootNode) rootNode .sum(function(d) { return d.value; }) .sort(function(a, b) { return b.height - a.height || b.value - a.value; }); treemapLayout(rootNode); let nodes = d3.select('svg g') .selectAll('g') .data(rootNode.descendants()) nodes .exit().remove() nodes = nodes .enter() .filter(function(d) { return d.depth < 3; }) .append('g') .merge(nodes) .attr('transform', function(d) { return 'translate(' + [d.x0, d.y0] + ')' }) //nodes nodes.append('rect') .attr('width', function(d) { return d.x1 - d.x0; }) .attr('height', function(d) { return d.y1 - d.y0; }) .attr('style', function(d) { return ('fill:' + d3.interpolateRdYlGn(d.data.health)) }) .on('click', function(d) { console.log(d.data.name); update(d); }) nodes .append('text') .attr('dx', 4) .attr('dy', 14) .text(function(d) { return d.data.name; }) }; update(data);
 <script src="https://d3js.org/d3.v5.min.js"></script> <svg width="500" height="300"> <g></g> </svg>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM