d3.js - v3和v4 - 输入和更新差异 [英] d3.js - v3 and v4 - Enter and Update differences
问题描述
我试图让 y
的值使用d3.js v4创建一个圆圈。通过下面的代码,我可以像创建圈子的行为一样创建图表,但是当我尝试在v4中运行相同的代码时,它不再工作。我知道v4更新有一些差异,但我没有找到任何关于它的信息。所以我想知道是否有人可以帮助我在d3.js v4中运行此代码。
以下是使用v3的代码(它将使用v4破解):
p>
var svg = d3.select('body')。append('svg' ).attr('width',250).attr('height',250); // render the datafunction render(data){//绑定var circles = svg.selectAll('circle')。data(data); //输入circles.enter()。append('circle').attr('r',10); (更新圆圈.attr('cx',函数(d){返回d.x;}).attr('cy',函数(d){return d.y;}); //退出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创造者Mike Bostock在D3 v3中引入了一种神奇行为,他保留在D3 v3.x中,但决定放弃在D3 v4.x中。要了解更多信息,请点击此处:软件的优点是什么? / b>这就是他所说的:
引入了一个更改:附加到输入选择将现在将输入元素复制到更新中选择[...] D3 4.0消除了enter.append的魔力。 (事实上,D3 4.0完全消除了Enter与普通选择之间的区别:现在只有一个选择类别。)
让我们看看它。
以下是您的D3 v3代码: lang =jsdata-hide =truedata-console =truedata-babel =false>
var svg = d3.select('body')。append('svg').attr('width',250).attr('height', 250); //渲染数据函数render(data){//绑定var circles = svg.selectAll('circle')。data(data); //输入circles.enter()。append('circle').attr('r',10); (更新圆圈.attr('cx',函数(d){返回d.x;}).attr('cy',函数(d){return d.y;}); //退出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>
$ b
现在使用D3 v4的代码。它会打破:
$ b
var svg = d3 ('body')。append('svg').attr('width',250).attr('height',250); //渲染数据函数render(data){//绑定var circles = svg .selectAll( '圆圈')的数据(数据)。 //输入circles.enter()。append('circle').attr('r',10); (更新圆圈.attr('cx',函数(d){返回d.x;}).attr('cy',函数(d){return d.y;}); //退出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>
通过break,我的意思是会追加圈子,但他们不会收到
x
和y
属性,并且它们将默认为零。这就是为什么你会看到左上角的所有圈子。
解决方案:合并选项:
circles.enter()。append('circle')
.attr('r',10)
.merge(circles)//从现在开始,输入+ update
.attr('cx',function(d){
return dx;
})
.attr('cy',function(d ){
return dy;
});
根据 API ,
merge()
...
...通常用于合并数据连接后的输入和更新选择。在分别修改进入和更新元素后,您可以合并这两个选择并在两者上执行操作,而无需重复代码。
以下是代码与
merge()
:
$ b
var svg = d3.select('body')。append('svg').attr('width',250).attr('height',250); // render data function render(data){//绑定var circles = svg.selectAll('circle')。data(data); //输入circles.enter()。append('circle').attr('r',10).merge(circles)//从现在起,输入+ update .attr('cx',function(d){ return dx;}).attr('cy',function(d){return dy;}); //退出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>
I'm trying to get the values for
x
andy
to make a circles using d3.js v4. With the following code I manage to create the chart like behavior of the circles, but when I try to run the same code in v4 it doesn't work anymore. I know that there are some differences in the update to v4 but I didn't find any information about it. So i was wondering if someone can help me to run this code in d3.js v4.Here is the code using v3 (it will break using 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 is the expected behaviour, and I've explained this before in this answer (not a duplicate, though).
What happened is that Mike Bostock, D3 creator, introduced a magic behaviour in D3 v2, which he kept in D3 v3.x, but decided to abandon in D3 v4.x. To read more about that, have a look here: What Makes Software Good? This is what he says:
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.)
Let's see it.
Here is your code with 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>
Now the same code, with D3 v4. It will "break":
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>
By "break" I mean the circles will be appended, but they will not receive the
x
andy
properties in the "enter" selection, and they will default to zero. That's why you see all circles at the top left corner.Solution: merge the selections:
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; });
According to the 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.
Here is the code with
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>
这篇关于d3.js - v3和v4 - 输入和更新差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!