为什么我对 Selection.join() 的调用没有返回输入选择?

Ral*_* B. 4 javascript d3.js

我已经设法使用创建一些<g>标签selection.join()。完成连接后,我想获得<g>方法链接的所有现有标签的完整列表的新选择,即之前存在的标签加上已创建的标签减去已销毁的标签。我如何从joinedNodes变量中得到这个?

 private createOrRemovePanelGroups(chartPanelsGroup: any, panelsRectangles: Array<Rectangle>): any {

    const joinedNodes: any = chartPanelsGroup
      .selectAll('g')
      .data(panelsRectangles)
      .join(
          enter => {
          enter.append('g');
      });
Run Code Online (Sandbox Code Playgroud)

在下面的第二个示例中,该方法采用矩形的选定<g>区域selectedParentNode和描述符。它必须在这里绘制唯一的矩形。我使用 id 来选择它。在第一次运行中它被创建,但它不包含在 . 返回的选择中.join()。因此,对于新创建的矩形,不会执行最后 4 行。但是,如果第二次执行并且矩形已经存在,则执行这些行,然后设置属性。

static drawRectangle(selectedParentNode: any, rectangle: Rectangle, uniqueId: any, classStyle: any) {

selectedParentNode
  .selectAll('#' + uniqueId)
  .data([{rectangle}])
  .join(
    (enter: any) => {
      enter
        .append('rect')
        .attr('id', uniqueId);
    },
    (update: any) => update
  )
  .attr('x',  rectangle.getLeftX())
  .attr('y', rectangle.getTopY())
  .attr('width',  rectangle.getWidth())
  .attr('height', rectangle.getHeight())
  .attr('class', classStyle);
}
Run Code Online (Sandbox Code Playgroud)

我的具体问题可以归结为以下MCVE。为什么选择返回的是.join()空?

 private createOrRemovePanelGroups(chartPanelsGroup: any, panelsRectangles: Array<Rectangle>): any {

    const joinedNodes: any = chartPanelsGroup
      .selectAll('g')
      .data(panelsRectangles)
      .join(
          enter => {
          enter.append('g');
      });
Run Code Online (Sandbox Code Playgroud)
static drawRectangle(selectedParentNode: any, rectangle: Rectangle, uniqueId: any, classStyle: any) {

selectedParentNode
  .selectAll('#' + uniqueId)
  .data([{rectangle}])
  .join(
    (enter: any) => {
      enter
        .append('rect')
        .attr('id', uniqueId);
    },
    (update: any) => update
  )
  .attr('x',  rectangle.getLeftX())
  .attr('y', rectangle.getTopY())
  .attr('width',  rectangle.getWidth())
  .attr('height', rectangle.getHeight())
  .attr('class', classStyle);
}
Run Code Online (Sandbox Code Playgroud)

alt*_*lus 5

用文档的话来说:

# 选择join (输入[,更新][,退出]) <>

根据需要追加、删除和重新排序元素,以匹配先前由选择.data绑定的数据,返回合并的输入和更新选择。

这意味着selection.join()应该已经返回您想要的选择,即更新节点和新输入节点的合并选择。正如您在代码中亲眼目睹的那样,由于文档中未涵盖的小细节,情况并非如此。

如果您传入函数以对.join()输入、更新和退出时发生的情况进行细粒度控制,则前两个函数(输入和更新)必须返回它们所作用的相应选择(即分别返回输入或更新选择) )!

在您的代码片段中,输入选择的处理函数是一个箭头函数,执行不返回任何选择的代码块。因此,进入的节点不包含在 返回的选择中.join()。根据这些处理函数正在执行的操作的复杂性,基本上有两种方法可以解决此问题:

  1. 对于简单的情况,只需省略大括号即可让箭头函数返回表达式的值:

    .join(enter => enter.append('g'));        
    
    Run Code Online (Sandbox Code Playgroud)
  2. 对于更复杂的情况,您可以轻松地从代码块中返回选择:

    .join(enter => {
      // ...do some serious stuff first.
    
      // append the entering nodes
      enter = enter.append("g")
    
      // ...followed by even more action.
    
      // Finally return the selection.
      return enter;
    }
    
    Run Code Online (Sandbox Code Playgroud)

请注意,这对于您已经使用上述 (1.) 解决方案的第二个片段中的更新选择来说是如何正确的。

您的 MCVE 可以轻松进行相应调整:

.join(enter => enter.append('g'));        
Run Code Online (Sandbox Code Playgroud)
.join(enter => {
  // ...do some serious stuff first.

  // append the entering nodes
  enter = enter.append("g")

  // ...followed by even more action.

  // Finally return the selection.
  return enter;
}
Run Code Online (Sandbox Code Playgroud)


流氓使用(不适合胆小的人) ——与您的特定问题无关。

Enter 或 update 处理函数返回的选择类型没有限制;您也可以返回任何选择,甚至是空选择或完全不相关的选择。返回的选择.join()包括由输入和更新处理程序返回的选择合二为一。尽管我无法提出用于这种越野用途的应用程序,但可能值得将这些知识牢记在心。