【问题标题】:How to update data in stack bar chart in D3如何在 D3 中更新堆栈条形图中的数据
【发布时间】:2013-08-19 17:31:15
【问题描述】:

我可以第一次填充堆积条形图,但我的要求是在单击按钮时使用新数据更新堆积条形图。单击按钮时,我正在调用后端并获取数据,请您指导我如何更新堆积条形图。我的问题是将新数据传递给条形图。

 d3.json("http://myhost/ITLabourEffortChart/effort/effort",function(error, data){
    color.domain(d3.keys(data.effort[0]).filter(function(key) { 
        return key !== "qName"; }));
data.effort.forEach(function(d) {
var y0 = 0;
d.effortHr = color.domain().map(function(name) { 
    return {name: name, y0: y0, y1: y0 += +d[name]}; });

d.total = d.effortHr[d.effortHr.length - 1].y1;


});
x.domain(data.effort.map(function(d) { return d.qName; }));
y.domain([0, d3.max(data.effort, function(d) { 
    return d.total; })]);

svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
.append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", ".71em")
  .style("text-anchor", "end")
  .text("FTE");

var state = svg.selectAll(".layer")
  .data(data.effort)
.enter().append("g")
  .attr("class", "g")
  .attr("transform", function(d) { return "translate(" + x(d.qName) + ",0)"; });

 rect = state.selectAll("rect")
 .attr("id", "barchart") 
  .data(function(d) { 
      return d.effortHr; })
.enter().append("rect")
  .attr("width", x.rangeBand())
  .attr("y", function(d) { 
      return y(d.y1); })
  .attr("height", function(d) { return y(d.y0) - y(d.y1); })
  .style("fill", function(d) { return color(d.name); });


On Update i am calling below method
function redraw() {
    d3.json("http://localhost:8080/ITLabourEffortChart/effort/effort/YrReports",function(error, data){

        color.domain(d3.keys(data.effort[0]).filter(function(key) {

            return key !== "qName"; }));
    data.effort.forEach(function(d) {
    var y0 = 0;
    d.ages = color.domain().map(function(name) { 
        return {name: name, y0: y0, y1: y0 += +d[name]}; });
    d.total = d.ages[d.ages.length - 1].y1;
    });

     var updatebar = svg.selectAll("#barchart");
    // Update…
     updatebar
     .transition()
    .duration(500)
    .delay(function(d, i) { return i * 10; })
  .transition()
    .attr("width", x.rangeBand())
  .attr("y", function(d) { 
      return y(d.y1); })
  .attr("height", function(d) { return y(d.y0) - y(d.y1); })
  .style("fill", function(d) { return color(d.name); }
  .attr("x", function(d) { 
    return x(d.x); })

  );

    });
  .attr("x", function(d) { 
    return x(d.x); })

  );

    });

【问题讨论】:

    标签: d3.js stacked


    【解决方案1】:

    要更新您的数据,您只需再次选择 svg 元素并重新绑定数据。在您的示例中,您已经选择了#barchart,现在您只需要重新绑定数据。你可以像第一次创建 svg 元素时那样做。所以这样的事情应该可以解决问题:

    var updatebar = svg.selectAll("#barchart");
    .data(newdata)
    .transition()
    .duration(500)
    ... (etc.)
    

    这里你可以找到更详细的解释: http://chimera.labs.oreilly.com/books/1230000000345/ch09.html#_updating_data

    更新:

    好的,很遗憾我不能使用 Fiddle,所以我只是在这里发布我的工作代码。据我所知,您的 selectAll 有问题,因为没有名为 .effort 的元素。这是您的重绘功能的更新代码:

    function redraw() {
    
        var effort = [];
        var obj = {
            pfte: "20",
            efte: "50",
            qName: "Q1"
        };
        var obj2 = {
            pfte: "10",
            efte: "13",
            qName: "Q2"
        };
    
        effort[0] = obj;
        effort[1] = obj2;
        var newDataSet = new Object();
        newDataSet.effort = effort;
    
        color.domain(d3.keys(newDataSet.effort[0]).filter(function (key) {
            return key !== "qName";
        }));
    
        effortDataSet = newDataSet.effort;
        effortDataSet.forEach(function (d) {
            var y0 = 0;
            d.effortHr = color.domain().map(function (name) {
                return { name: name, y0: y0, y1: y0 += +d[name] };
            });
            d.total = d.effortHr[d.effortHr.length - 1].y1;
        });
    
        state = svg.selectAll(".g")
            .data(effortDataSet)
            .attr("class", "g")
            .attr("transform", function (d) { return "translate(" + x(d.qName) + ",0)"; });
    
        state = state.selectAll("rect")
            .data(function (d) {
                return d.effortHr;
            })
            .attr("width", x.rangeBand())
            .attr("y", function (d) {
                return y(d.y1);
            })
            .attr("height", function (d) {
            //console.log(y(d.y0) - y(d.y1));
            return y(d.y0) - y(d.y1);
            })
            .style("fill", function (d) { return color(d.name); });
    }
    

    【讨论】:

    • 我已经创建了这样的堆积条形图 [堆积图][1] [1]:gist.github.com/mbostock/3886208 但我想更新此图表中的数据。我的数据集随着轴名称和值的变化而变化。但我不能只实现简单的数据更改。非常感谢这方面的任何帮助。
    • 好的,我认为问题如下:您首先将数据集绑定到您的元素。这意味着您的数据被复制到您的元素中。接下来,您使用数据从原始数据 (d.effortHr) 中获取子数据。在这期间您更改了数据集,但绑定到您的元素的数据仍然相同,因为它已被复制。使用 .data(effortDataSet) 再次更改数据集后,尝试真正重新绑定数据集
    • 我可以重新绘制新值,但旧条没有被删除,它只是与旧值重叠。 var block = state.selectAll("rect") .data(function(d) { return d.effortHr; }); block.enter().append("rect") .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.y1); }) .attr( “高度”,函数(d){返回y(d.y0)-y(d.y1);}).style(“填充”,函数(d){返回颜色(d.name);}); //block.exit().attr("transform", function(d) {console.log(d); return "translate(" + x(d.qName) + ",0)"; }).remove( ); block.exit().remove();
    • 确保您处理两个单独的步骤:1) 初始步骤,您使用初始数据创建 svg 元素。 2)更新重新绑定数据的步骤(已更改)。我认为您的选择有问题。
    • 我忘记了:确保在更新步骤中不要再次输入或追加。您的元素已经存在,因此您只需要更新它们的数据并使用新值再次更改属性...
    猜你喜欢
    • 2013-06-26
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    相关资源
    最近更新 更多