d3每月数据集 - 更新数据 - 添加新组

suM*_*uMi 5 javascript d3.js

我正在研究用于学习d3的个人财务的可视化,其中有些东西感觉像是一个有用的项目.我已经设法按照我想要的方式制作图表(每日+或减去).现在我希望能够从一个月改为下一个月.如果旧月(更新前)有更多天(也称为数据点)而不是新月(更新后),则此方法有效.如果旧数据点的数据点少于新数据点,则会在图表顶部添加其他数据点.我将条形图中的每个数据点添加为一个组(条形本身,数据标签+日期标签).我正在为每个新的一天向下翻译整个小组.我需要弄清楚的是,如果在更新后我有更多或更少的数据点,如果我有更少,我需要向下翻译新的数据点.你知道我的意思?这是我最初添加条形图的代码:

bar = chart.selectAll("g")
      .data(data)
      .enter().append("g")
      .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
    //bar


//grey background bars 
  bar.append("rect")
          .attr("class", "backgroundBar")
          .attr("x", 10)
          .attr("width", (width-30))
          .attr("height", barHeight-1)
          .attr("fill", "#dddddd")
          .attr("fill-opacity", "0.3");

  //dateLabel
  bar.append("text")
        .attr("class", "dateLabel")
        .attr("x", width/2-20)
        .attr("y", barHeight-5)
       .attr("fill", "black")
        .text(function(d){ return d.key})
  bar.append("rect")
          .attr("class", "bar")
          .attr("x", function(d) { if(scale(d.values.total)<0){return width/2+widthDateLabel;}else{return width/2-scale(d.values.total)-widthDateLabel;}})
          .attr("width", function(d) { return Math.abs(scale(d.values.total)); })
          .attr("height", barHeight - 1)
          .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}});
  //BarLabel
  bar.append("text")
        .attr("class", "barLabel")
        .attr("x",function(d) { if(scale(d.values.total)<0){return window.width/2-scale(d.values.total)+5+widthDateLabel;}else{return window.width/2-scale(d.values.total)-5-widthDateLabel;}})
        .attr("y", barHeight/2)
        .attr("dy", ".35em")
        .attr("text-anchor", function(d) { if(scale(d.values.total)<0){ return "start"}else{return "end"}})
        .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}})
        .text(function(d) { return Math.round(d.values.total*100)/100; });
Run Code Online (Sandbox Code Playgroud)

我显然不能与小组合作但是翻译每个y坐标,但感觉就像一个肮脏的解决方案,不是吗?以下是问题的屏幕截图:在此输入图像描述

编辑:这是我目前的更新功能.有效,但在屏幕截图中产生结果

//update the bar itself


var bar=chartgroups.selectAll(".bar")
          .data(data);
  bar.enter().append("rect")
          .attr("class", "bar")
          .attr("x", function(d) { if(scale(d.values.total)<0){return width/2+widthDateLabel;}else{return width/2-scale(d.values.total)-widthDateLabel;}})
          .attr("width", function(d) { return Math.abs(scale(d.values.total)); })
          .attr("height", barHeight - 1)
          .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}});
  bar.exit().remove();
  bar
    .transition().duration(750)
      .attr("height", barHeight - 1)
      .attr("x", function(d) { if(scale(d.values.total)<0){return width/2+widthDateLabel;}else{return width/2-scale(d.values.total)-widthDateLabel;}})
      .attr("width", function(d) { return Math.abs(scale(d.values.total)); })
      .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}});

  //update the barLabel
  var barLabel=chart.selectAll(".barLabel").data(data);
  barLabel.enter().append("text")
        .attr("x",function(d) { if(scale(d.values.total)<0){return window.width/2-scale(d.values.total)+5+widthDateLabel;}else{return window.width/2-scale(d.values.total)-5-widthDateLabel;}})
        .attr("y", barHeight/2)
        .attr("dy", ".35em")
        .attr("text-anchor", function(d) { if(scale(d.values.total)<0){ return "start"}else{return "end"}})
        .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}})
        .text(function(d) { return Math.round(d.values.total*100)/100; });
  barLabel.exit().remove();
  barLabel
    .transition().duration(750)
      .attr("x",function(d) { if(scale(d.values.total)<0){return window.width/2-scale(d.values.total)+5+widthDateLabel;}else{return window.width/2-scale(d.values.total)-5-widthDateLabel;}})
      .attr("y", barHeight/2)
      .attr("text-anchor", function(d) { if(scale(d.values.total)<0){ return "start"}else{return "end"}})
      .attr("fill", function(d) { if(scale(d.values.total)<0){ return "DeepPink"}else{return "MediumSeaGreen"}})
      .text(function(d) { return Math.round(d.values.total*100)/100; });

  //update dates
  var dateLabel=chart.selectAll(".dateLabel").data(data);
  dateLabel.enter().append("text")
        .attr("class", "dateLabel")
        .attr("x", width/2-20)
        .attr("y", barHeight-5)
        .attr("fill", "black")
        .text(function(d){ return d.key})
  dateLabel.exit().remove();
  dateLabel
    .transition().duration(750)
        .text(function(d){ return d.key})
        .attr("y", barHeight-5)

  //update background bars
  var backgroundBar=chart.selectAll(".backgroundBar").data(data);
  backgroundBar.enter().append("rect")
          .attr("class", "backgroundBar")
          .attr("x", 10)
          .attr("width", (width-30))
          .attr("height", barHeight-1)
          .attr("fill", "#dddddd")
          .attr("fill-opacity", "0.3");
  backgroundBar.exit().remove();
  backgroundBar
    .transition().duration(750)
      .attr("height", barHeight-1)
Run Code Online (Sandbox Code Playgroud)

MrH*_*Hen 2

您需要做一些事情:

  1. 更新您的数据集。
  2. 用新东西更新 D3 选择
  3. 从 D3 选择中删除所有已删除的内容
  4. 使用过渡对任何更新的内容进行动画处理

一个简单的例子:

data.unshift(newData); // #1; add new data at the beginning
// (You could also remove stuff; update data in the middle; do whatever you need.)

var selection = chart.selectAll("g")
    .data(data, function(d) { return d.id; }));

selection.enter() // #2; Add the new stuff just like you did before
    .append("g")
    .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });

// . . . all the other setup goes here, too

selection.exit() // #3; Hide any removed elements (should slide them down and turn them invisible)
    .transition().duration(400)
    .attr("transform", function(d, i) { return "translate(0," + (i + 1) * barHeight + ")"; });
    .style("opacity", 0)
    .remove();

selection // #4; Move everything to the right location
    .transition().duration(400)
    .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
Run Code Online (Sandbox Code Playgroud)

本系列中有一些关于如何进行此类更新的非常好的示例:常规更新模式

需要明确注意的一个问题涉及关键功能。您必须包含一个与我上面添加的类似的关键功能 - 通读通用更新模式文章,它应该解释您需要了解的内容。