比较/差异新数据与d3.js更新的先前数据

 大Joob 发布于 2023-01-18 08:48

我想表示当前数据集与客户计算的先前数据集之间的差异.

想象一下,我已经有三个圈子,绑定到数据[1, 2, 3].现在我想更新数据并根据新值和旧值之间的差异做些什么?

var new_data = [2, 2, 2]; // This is the new data I'd like to compare with the old

svg.selectAll("circle").data(new_data)
    .transition().duration(2000)
.attr("fill", "red") // e.g. I'd like to colour the circles red if the change
                     // is negative, blue if positive, black if no change.
.attr("r", function(d) { return d * 10; });

这是一个JSFiddle,将上面的代码设置为一个例子.

2 个回答
  • 您有两个选项可用于保存附加到元素的旧数据,以便在新数据连接后识别更改.

    如您所建议的,第一个选项是使用数据属性.这个SO Q&A描述了这种方法.需要考虑的事项:

    您的所有数据值都将被强制转换为字符串

    您需要为数据的每个方面单独的方法调用/属性

    你正在操纵DOM,所以如果你有很多元素或大量数据,它可能会减慢速度

    数据现在是DOM的一部分,因此可以与图像一起保存或由其他脚本访问

    第二种选择是将数据存储为元素的DOM对象的Javascript属性,就像d3 将活动数据存储为__data__属性一样.我在这个论坛帖子中讨论了这个方法.

    一般方法:

    selection = selection.property(" __oldData__", function(d){ return d; } ); 
                            //store the old data as a property of the node
                        .data(newData, dataKeyFunction);  
                            //over-write the default data property with new data
                            //and store the new data-joined selection in your variable
    
    selection.enter() /*etc*/;  
    
    selection.attr("fill",  function(d) {
                     // Within any d3 callback function,
                     // you can now compare `d` (the new data object)
                     // with `this.__oldData__` (the old data object).
                     // Just remember to check whether `this.__oldData__` exists
                     // to account for the just-entered elements.
    
                    if (this.__oldData__) { //old data exists
    
                      var dif = d.value - this.__oldData__.value; 
                      return (dif) ? //is dif non-zero?
                             ( (dif > 0)? "blue" : "red" ) :
                             "black" ; 
                    } else {
                      return "green"; //value for new data
                    }
    
                });
    
    selection.property("__oldData__", null); 
              //delete the old data once it's no longer needed
              //(not required, but a good idea if it's using up a lot of memory)
    

    您当然可以使用旧数据属性的任何名称,只是在其周围抛出大量"_"字符以避免弄乱任何浏览器的本机DOM属性.

    2023-01-18 08:51 回答
  • 从D3 v4开始,您可以使用内置的局部变量支持.内部实现与AmeliaBR的回答基本相同,但它让您不必自己存储旧数据.使用时,d3.local()您可以设置一个作用域为特定DOM节点的值,因此名称为局部变量.在下面的代码段中,这是针对每个圆圈进行的

    .each(function(d) { previousData.set(this, d) });  // Store previous data locally...
    

    您可以稍后检索存储在其上的任何特定节点的值:

    .attr("fill", function(d) {
      var diff = previousData.get(this) - d;  // Retrieve previously stored data.
      return diff  < 0 ? "red" : diff > 0 ? "blue" : "black";
    }) 
    

    这个完整的代码可能如下所示:

    var old_data = [1, 2, 3]; // When the data gets updated I'd like to 'remember' these values
    
    // Create a local variable for storing previous data.
    var previousData = d3.local();
    
    var svg = d3.select("body").append("svg")
        .attr("width", 500)
        .attr("height", 200);
    
    var p = d3.select("body")
      .append("p")
        .text("Old data. Click on the circles to update the data.");
    
    var circle = svg.selectAll("circle")
      .data(old_data)
      .enter().append("circle")
        .attr("fill", "black")
        .attr("r", function(d) { return d * 10; })
        .attr("cx", function(d){ return d * 40; })
        .attr("cy", function(d){ return d * 40; })
        .each(function(d) { previousData.set(this, d) });  // Store previous data locally on each node
    
    svg.on("click", function(d) {
      p.text("Updated data.");
      var new_data = [2, 2, 2]; // This is the new data I'd like to compare with the old
        
      circle.data(new_data)
        .transition().duration(2000)
          .attr("fill", function(d) {
            var diff = previousData.get(this) - d;  // Retrieve previously stored data.
            return diff  < 0 ? "red" : diff > 0 ? "blue" : "black";
          }) 
          .attr("r", function(d) { return d * 10; });
    });
    <script src="https://d3js.org/d3.v4.js"></script>
    2023-01-18 08:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有