d3.js v4: How to access parent group's datum index?

前端 未结 8 691
萌比男神i
萌比男神i 2020-11-28 10:33

The description of the selection.data function includes an example with multiple groups (link) where a two-dimensional array is turned into an HTML table.

相关标签:
8条回答
  • 2020-11-28 11:21

    Well, sometimes an answer doesn't provide a solution, because the solution may not exist. This seems to be the case.

    According to Bostock:

    I’ve merged the new bilevel selection implementation into master and also simplified how parents are tracked by using a parallel parents array.

    A nice property of this new approach is that selection.data can evaluate the values function in exactly the same manner as other selection functions: the values function gets passed {d, i, nodes} where this is the parent node, d is the parent datum, i is the parent (group) index, and nodes is the array of parent nodes (one per group). Also, the parents array can be reused by subselections that do not regroup the selection, such as selection.select, since the parents array is immutable.

    This change restricts functionality—in the sense that you cannot access the parent node from within a selection function, nor the parent data, nor the group index — but I believe this is ultimately A Good Thing because it encourages simpler code.

    (emphasis mine)

    Here's the link: https://github.com/d3/d3-selection/issues/47

    So, it's not possible to get the index of the parent's group using selection (the parent's group index can be retrieved using selection.data, as this snippet bellow shows).

    var testData = [
    [
      {x: 1, y: 40},
      {x: 2, y: 43},
      {x: 3, y: 12},
      {x: 6, y: 23}
    ], [
      {x: 1, y: 12},
      {x: 4, y: 18},
      {x: 5, y: 73},
      {x: 6, y: 27}
    ], [
      {x: 1, y: 60},
      {x: 2, y: 49},
      {x: 3, y: 16},
      {x: 6, y: 20}
     ] 
    ];
    
    var svg = d3.select("body")
    	.append("svg")
      .attr("width", 300)
      .attr("height", 300);
      
    var g = svg.selectAll(".groups")
        .data(testData)
        .enter()
        .append("g");
        
    var rects = g.selectAll("rect")
        .data(function(d, i , j) { console.log("Data: " + JSON.stringify(d), "\nIndex: " + JSON.stringify(i), "\nNode: " + JSON.stringify(j)); return d})
        .enter()
        .append("rect");
    <script src="https://d3js.org/d3.v4.min.js"></script>

    0 讨论(0)
  • 2020-11-28 11:23

    Here's a snippet I crafter after re-remembering this usage of .each for nesting, I thought it may be useful to others who end up here. This examples creates two layers of circles, and the parent group index is used to determine the color of the circles - white for the circles in the first layer, and black for the circles in the top layer (only two layers in this case).

    const nested = nest().key(layerValue).entries(data);
    
    let layerGroups = g.selectAll('g.layer').data(nested);
    layerGroups = layerGroups.enter().append('g').attr('class', 'layer')
      .merge(layerGroups);
    
    layerGroups.each(function(layerEntry, j) {   
      const circles = select(this)
        .selectAll('circle').data(layerEntry.values);
      circles.enter().append('circle')
        .merge(circles)
          .attr('cx', d => xScale(xValue(d)))
          .attr('cy', d => yScale(yValue(d)))
          .attr('r', d => radiusScale(radiusValue(d)))
          .attr('fill', j === 0 ? 'white' : 'black'); // <---- Access parent index.
    });
    
    0 讨论(0)
提交回复
热议问题