在单个链中更新,输入和退出选择

时间:2019-02-13 06:07:41

标签: javascript d3.js

我正在使用D3创建反应性可视化。每当数据更改时,我都会大量使用这种模式:

function redraw(myData) {
    // if data points decreased, remove some rectangles
    d3.selectAll('rect')
        .data(myData)
        .exit()
        .remove();
    // if data points increased, add some rectangles
    d3.selectAll('rect')
        .data(myData)
        .enter()
        .append('rect');
    // assign attribute values to all rectangles
    d3.selectAll('rect')
        .data(myData)
        .attr('width', (d) => d.width)
        .attr('height', (d) => d.height)
        .attr('fill', 'blue');
}

有没有办法将此操作缩短为一个较长的操作链?

我看过许多{3}这样的D3例子,这些例子适合一次抽奖。我无法让他们为重画工作。

1 个答案:

答案 0 :(得分:3)

join()方法

您问...

  

是否可以将此操作缩短为单个长链操作? (强调我的)

是的,有:如果您使用的是D3 v5.8或更高版本,则可以利用新方法selection.join()updateenter制作一条链和exit选择。顺便说一下,您链接的示例(由D3创建者Bostock制作)已经在使用join(),所以它不是“一次性抽奖”

您的整个功能将是:

function redraw(myData) {
    d3.select(foo).selectAll('rect')
        .data(myData)
        .join('rect')
        .attr('width', (d) => d.width)
        .attr('height', (d) => d.height)
        .attr('fill', 'blue');
};

这是一个基本演示:

const svg = d3.select("svg");

d3.interval(function() {
  redraw(getData());
}, 1500);

redraw(getData());

function redraw(myData) {
  svg.selectAll('rect')
    .data(myData)
    .join('rect')
    .attr('width', (d) => d.width)
    .attr('height', (d) => d.height)
    .attr('x', (d) => d.x)
    .attr('y', (d) => d.y)
    .style('fill', 'lavender')
    .style('stroke', '#444');
};

function getData() {
  return d3.range(~~(Math.random() * 20)).map(function(d) {
    return {
      x: Math.random() * 250,
      y: Math.random() * 100,
      width: 10 + Math.random() * 40,
      height: 10 + Math.random() * 40,
    }
  });
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>


PS :您当前的功能存在一些问题。首先,d3.selectAllselection.selectAll不同(请注意我的函数中的d3.select(foo))。其次,在该函数中没有正确的updateenterexit选择。看看here的惯用模式。

相关问题