我正在学习D3并且在更新条形图时遇到问题
let container = d3.select(this)
let x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
let y = d3.scaleLinear().rangeRound([height, 0])
x.domain(data.map(function(d) {
return d.x;
}));
y.domain([0, d3.max(data, function(d) { return d.y; })])
// seems like everytime when there is a new data, a new "g" is appended
let g = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const gEnter = g.selectAll('.bar')
.data(data)
gEnter.exit().remove()
gEnter.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.x)
})
.attr("y", function(d) {
return y(d.y)
})
.attr('fill', barColor)
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.y)
})
我的目标是每当有新数据进入时更新图表,上面的代码所做的就是在当前图表的顶部附加新图表。
不知怎的,我觉得我错过了一些微不足道的东西。任何提示都会有所帮助,谢谢。
答案 0 :(得分:0)
你应该移动
let g = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
更新函数,否则,每次执行此函数时都会创建一个新的g
,在这个新的selectAll
上创建一个g
(并且在其中找不到任何内容) ,并对所有数据执行enter()
选择。
您可以将结构更改为:
const svg = d3.select(this),
container = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
let x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
let y = d3.scaleLinear().rangeRound([height, 0])
function update(data){
x.domain(data.map(function(d) {
return d.x;
}));
y.domain([0, d3.max(data, function(d) { return d.y; })])
const gEnter = container.selectAll('.bar')
.data(data)
gEnter.exit().remove()
gEnter.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.x)
})
.attr("y", function(d) {
return y(d.y)
})
.attr('fill', barColor)
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.y)
})
}
someAjaxCall().then(data => update(data))
您可以查看Mike Bostock撰写的example,了解如何整理代码。