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

Ric*_*ard 3 html javascript version d3.js

我正在尝试使用d3.js v4 获取值xy制作圆圈.使用以下代码,我设法创建图表,就像圈子的行为,但当我尝试在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);
Run Code Online (Sandbox Code Playgroud)
<script src='https://d3js.org/d3.v3.min.js'></script>
Run Code Online (Sandbox Code Playgroud)

Ger*_*ado 9

这是预期的行为,我在此答案之前已经解释了这一点(尽管不是重复的).

发生了什么事情,D3创造者Mike Bostock在D3 v2中引入了一个神奇的行为,他保留在D3 v3.x中,但决定放弃D3 v4.x. 要了解更多相关信息,请查看此处:什么使软件变得更好?这就是他所说的:

D3 2.0引入了一个改变:附加到输入选择现在将输入元素复制到更新选择中[...] D3 4.0删除了enter.append的魔力.(事实上​​,D3 4.0完全消除了输入和正常选择之间的区别:现在只有一类选择.)

让我们来看看它.

这是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);
Run Code Online (Sandbox Code Playgroud)
<script src='https://d3js.org/d3.v3.min.js'></script>
Run Code Online (Sandbox Code Playgroud)

现在使用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);
Run Code Online (Sandbox Code Playgroud)
<script src='https://d3js.org/d3.v4.min.js'></script>
Run Code Online (Sandbox Code Playgroud)

通过"break"我的意思是将附加圆圈,但它们不会在"enter"选项中接收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;
  });
Run Code Online (Sandbox Code Playgroud)

根据API,merge()......

...通常用于在数据连接后合并输入和更新选择.单独修改输入和更新元素后,您可以合并这两个选项并在两个选项上执行操作而无需重复代码.

这是代码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);
Run Code Online (Sandbox Code Playgroud)
<script src='https://d3js.org/d3.v4.min.js'></script>
Run Code Online (Sandbox Code Playgroud)