javascript - d3.js - v3 和 v4 - 输入和更新差异

标签 javascript html d3.js version

我正在尝试获取 xy 的值以使用 d3.js v4 制作一个圆圈。使用以下代码,我设法创建了类似于圆圈行为的图表,但是当我尝试在 v4 中运行相同的代码时,它不再起作用了。我知道 v4 的更新有一些差异,但我没有找到任何相关信息。所以我想知道是否有人可以帮助我在 d3.js v4 中运行这段代码。

这是使用 v3 的代码(使用 v4 会中断):

var svg = d3.select('body').append('svg')
  .attr('width', 250)
  .attr('height', 250);

//render the data
function render(data) {
  //Bind 
  var circles = svg.selectAll('circle').data(data);

  //Enter
  circles.enter().append('circle')
    .attr('r', 10);
  //Update
  circles
    .attr('cx', function(d) {
      return d.x;
    })
    .attr('cy', function(d) {
      return d.y;
    });


  //Exit
  circles.exit().remove();
}



var myObjects = [{
  x: 100,
  y: 100
}, {
  x: 130,
  y: 120
}, {
  x: 80,
  y: 180
}, {
  x: 180,
  y: 80
}, {
  x: 180,
  y: 40
}];


render(myObjects);
<script src='https://d3js.org/d3.v3.min.js'></script>

最佳答案

这是预期的行为,我之前在 this answer 中对此进行了解释(虽然不是重复的)。

D3 的创建者 Mike Bostock 在 D3 v2 中引入了一种神奇的行为,他在 D3 v3.x 中保留了这种行为,但决定在 D3 v4.x 中放弃。要了解更多相关信息,请查看此处:What Makes Software Good?他是这样说的:

D3 2.0 introduced a change: appending to the enter selection would now copy entering elements into the update selection [...] D3 4.0 removes the magic of enter.append. (In fact, D3 4.0 removes the distinction between enter and normal selections entirely: there is now only one class of selection.)

让我们看看。

这是您使用 D3 v3 的代码:

var svg = d3.select('body').append('svg')
  .attr('width', 250)
  .attr('height', 250);

//render the data
function render(data) {
  //Bind 
  var circles = svg.selectAll('circle').data(data);

  //Enter
  circles.enter().append('circle')
    .attr('r', 10);
  //Update
  circles
    .attr('cx', function(d) {
      return d.x;
    })
    .attr('cy', function(d) {
      return d.y;
    });

  //Exit
  circles.exit().remove();
}

var myObjects = [{
  x: 100,
  y: 100
}, {
  x: 130,
  y: 120
}, {
  x: 80,
  y: 180
}, {
  x: 180,
  y: 80
}, {
  x: 180,
  y: 40
}];


render(myObjects);
<script src='https://d3js.org/d3.v3.min.js'></script>

现在使用相同的代码,使用 D3 v4。它会“崩溃”:

var svg = d3.select('body').append('svg')
  .attr('width', 250)
  .attr('height', 250);

//render the data
function render(data) {
  //Bind 
  var circles = svg.selectAll('circle').data(data);

  //Enter
  circles.enter().append('circle')
    .attr('r', 10);
  //Update
  circles
    .attr('cx', function(d) {
      return d.x;
    })
    .attr('cy', function(d) {
      return d.y;
    });

  //Exit
  circles.exit().remove();
}

var myObjects = [{
  x: 100,
  y: 100
}, {
  x: 130,
  y: 120
}, {
  x: 80,
  y: 180
}, {
  x: 180,
  y: 80
}, {
  x: 180,
  y: 40
}];


render(myObjects);
<script src='https://d3js.org/d3.v4.min.js'></script>

我所说的“中断”是指圆圈将被附加,但它们不会收到“输入”选择中的 xy 属性,它们将默认归零。这就是您在左上角看到所有圆圈的原因。

解决方案:合并选择:

circles.enter().append('circle')
  .attr('r', 10)
  .merge(circles) //from now on, enter + update
  .attr('cx', function(d) {
    return d.x;
  })
  .attr('cy', function(d) {
    return d.y;
  });

根据API , merge()...

... is commonly used to merge the enter and update selections after a data-join. After modifying the entering and updating elements separately, you can merge the two selections and perform operations on both without duplicate code.

这是带有 merge() 的代码:

var svg = d3.select('body').append('svg')
  .attr('width', 250)
  .attr('height', 250);

//render the data
function render(data) {
  //Bind 
  var circles = svg.selectAll('circle').data(data);

  //Enter
  circles.enter().append('circle')
    .attr('r', 10)
    .merge(circles) //from now on, enter + update
    .attr('cx', function(d) {
      return d.x;
    })
    .attr('cy', function(d) {
      return d.y;
    });

  //Exit
  circles.exit().remove();
}

var myObjects = [{
  x: 100,
  y: 100
}, {
  x: 130,
  y: 120
}, {
  x: 80,
  y: 180
}, {
  x: 180,
  y: 80
}, {
  x: 180,
  y: 40
}];


render(myObjects);
<script src='https://d3js.org/d3.v4.min.js'></script>

关于javascript - d3.js - v3 和 v4 - 输入和更新差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47032051/

相关文章:

javascript - 如何让 SVG 圆沿 SVG 路径拖动?

javascript - 单击即可在数据集之间进行简单转换

javascript - OnClick 可以做两件事吗?

javascript - module.exports 中 "this"的范围

javascript - 我是否需要 Web Workers 来循环 AJAX 请求?

php - 分页器,如何使第一页和最后一页静态并放在点之间

javascript - 如何将 D3 图表的 JS 数组更改为 JS 对象

javascript - 仅在小型设备上调用 jQuery 函数

javascript - 用 Jquery 改变 div

html - CSS 空白 :pre in Cordova application not working