我尝试使用d3.js v4获取x
和y
的值来制作圆圈。使用以下代码,我设法创建图表,就像圈子的行为一样,但是当我尝试在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>
&#13;
答案 0 :(得分:8)
这是预期的行为,我之前在this answer解释了这一点(但不是重复)。
发生了什么事情,D3创造者Mike Bostock在D3 v2中引入了一个魔术行为,他保留在D3 v3.x中,但决定放弃D3 v4.x.要了解更多相关信息,请查看此处:What Makes Software Good?这就是他所说的:
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);
&#13;
<script src='https://d3js.org/d3.v3.min.js'></script>
&#13;
现在使用D3 v4的相同代码。它会&#34;打破&#34;:
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);
&#13;
<script src='https://d3js.org/d3.v4.min.js'></script>
&#13;
通过&#34;休息&#34;我的意思是圈子会被追加,但他们不会在&#34;输入&#34;中收到x
和y
属性。选择,它们将默认为零。这就是为什么你会看到左上角的所有圆圈。
解决方案:合并选择:
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()
...
...通常用于在数据连接后合并输入和更新选择。单独修改输入和更新元素后,您可以合并这两个选项并在两个选项上执行操作而无需重复代码。
以下是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);
&#13;
<script src='https://d3js.org/d3.v4.min.js'></script>
&#13;
答案 1 :(得分:1)
在d3v4中更改了更新模式。 摘录自documentation:
此外,selection.append不再合并进入节点 更新选择;使用selection.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) // <== !!!
.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://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>