D3 V4 使用带合并的通用更新模式输入元素时的转换

jtr*_*r13 5 javascript transition d3.js

据我所知,不可能在标准 enter/append/merge 链中的输入元素上包含转换,因为这样做会用无法与更新选择合并的转换替换输入元素选择。(有关选择和转换之间的区别,请参见此处)。

(针对评论编辑的问题)

如果想要的效果是顺序转换,合并前一个合并后一个,可以按如下方式完成:

// Join data, store update selection      
      circ = svg.selectAll("circle")
          .data(dataset);

// Add new circle and store entering circle selection        
      var newcirc = circ.enter().append("circle")
         *attributes*

// Entering circle transition        
      newcirc    
          .transition()
          .duration(1000)
          *modify attributes*
          .on("end", function () {

// Merge entering circle with existing circles, transition all        
      circ = newcirc.merge(circ)
          .transition()
          .duration(1000)
          *modify attributes*
      });
Run Code Online (Sandbox Code Playgroud)

提琴手

我想知道是否有办法在不破坏输入/追加/合并链的情况下做到这一点。

alt*_*lus 6

毫无疑问,您的方法链中必须至少有一个中断,因为您需要保留对更新选择的引用,以便稍后能够将其合并到输入选择中。如果您对此感到满意,则有一种方法可以在最初中断后保持链条完好无损。

我奠定了基本的校长这工作我回答:“你可以链接过渡后的功能,没有它作为过渡的一部分?” . 这使用transition.selection()它允许您摆脱当前过渡并访问开始过渡的基础选择。但是,您的代码更复杂,因为链式转换增加了复杂性。

第一部分是像之前一样存储更新选择:

// Join data, store update selection      
const circUpd = svg.selectAll("circle")
  .data(dataset);
Run Code Online (Sandbox Code Playgroud)

第二个不间断的部分是这样的:

const circ = circUpd              // 2. Store merged selection from 1.
  .enter().append("circle")
    // .attr()...
  .transition()
    // .duration(1000)
    // .attr()...
    .on("end", function () {
      circ.transition()           // 3. Use merged selection from 2.
        // .duration(1000)
        // .attr()...
    })
    .selection().merge(circUpd);  // 1. Merge stored update into enter selection.
Run Code Online (Sandbox Code Playgroud)

这可能需要对上面编号的步骤做一些进一步的解释:

  1. 最后一行是最重要的——在开始转换之后,代码.selection()用来获取转换所基于的选择,即输入选择,它反过来可以用来轻松地将存储的更新选择合并到它。

  2. 包含输入和更新选择的合并选择是整个链的结果,然后存储在circ.

  3. 这是棘手的部分!重要的是要理解,提供给的函数.on("end", function() {...})是一个回调,在转换结束之前不会执行。尽管这一行出现合并选择之前,但它实际上是合并之后执行的。circ然而,通过引用,它会结束——捕获,如果你愿意的话——对 的引用circ。这样,当回调实际执行时,circ将已经引用先前合并的选择。

看看下面的工作片段:

// Join data, store update selection      
const circUpd = svg.selectAll("circle")
  .data(dataset);
Run Code Online (Sandbox Code Playgroud)
const circ = circUpd              // 2. Store merged selection from 1.
  .enter().append("circle")
    // .attr()...
  .transition()
    // .duration(1000)
    // .attr()...
    .on("end", function () {
      circ.transition()           // 3. Use merged selection from 2.
        // .duration(1000)
        // .attr()...
    })
    .selection().merge(circUpd);  // 1. Merge stored update into enter selection.
Run Code Online (Sandbox Code Playgroud)

  • @jtr13 不仅*end* 事件保证在合并后执行,而且在当前任务完成之前整个转换甚至不会*started*。因此,即使你有一个 `.on("start")` 这也会看到合并的选择。 (2认同)