如何使用d3 Update Selection绘制稀疏矩阵

时间:2016-10-14 00:21:33

标签: javascript d3.js

我正在使用d3基于此示例绘制矩阵:http://bl.ocks.org/ianyfchang/8119685。 在我的矩阵中,每个元素表示来自行[x] =>的ping RTT值。列[y],例如如果服务器0 ping服务器1并返回100ms,那么在矩阵节点[0] [1] = 100中,当然可视化网络状态,我将在每个单元格中填充绿色,黄色或红色取决于相应的RTT。

在这种情况下,并非每个服务器都ping所有其他服务器,因此我得到的数据不是一个完整的网格,从数学上讲,它是一个稀疏矩阵,大多数元素都是null,数据看起来像这样:

src       dest       RTT
server0   server1    100
server150 server10   80
server100 server100  600
...

我还有所有服务器的完整列表,我将所有服务器名称绘制为行和列标签,然后将每个记录的src转换为服务器名称数组中服务器名称的索引。

这是问题所在,如果我通过cooked(煮熟意味着我将src和dest服务器名称转换为服务器列表数组中的索引)稀疏矩阵到d3,它只会在有ping记录时绘制单元格,让d3即使没有数据也绘制所有单元格,我需要创建一个完整的网格矩阵。在我阅读了d3更新的介绍后,进入和退出选择,我想我可能会这样做:

  1. 创建一个虚拟全网格矩阵,让d3绘制所有单元格;
  2. 使用我的真实矩阵更新d3.selectAll(" cell"),因此d3会自动更新那些具有真实ping RTT值的虚拟单元格。
  3. 这是我的代码,但它不起作用:(有人知道为什么吗?我有一种感觉,我应该控制我的真实矩阵如何加入元素,但我不知道如何使用.data()中的关键功能。

    var svg = d3.select("#matrix")
    .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
    .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    // create a dummy matrix and a dummy matrix
    var dummy = [];
    for (var i = 0; i < servers.length; ++i) {
        for (var j = 0; j < servers.length; ++j) {
            var n = {};
            n.x = i;
            n.y = j;
            dummy.push(n);
        }
    }
    
    var heatmap = svg.append("g").attr("class", "g3")
        .selectAll(".cellg")
        .data(dummy)
        .enter()
        .append("rect")
        .attr("x", function (d) { return d.y * cellSize; })
        .attr("y", function (d) { return d.x * cellSize; })
        .attr("class", function (d) { return "cell cell-border cr" + (d.x - 1) + " cc" + (d.y - 1); })
        .attr("width", cellSize)
        .attr("height", cellSize)
        .style("fill", function (d) { return d.Item3 === undefined ? "white" : d.m_Item3 >= 5000 ? "red" : d.m_Item3 >= 2000 ? "yellow" : "green"; })
        .on("mouseover", function (d) {
            d3.select(this).classed("cell-hover", true);
            d3.selectAll(".rowLabel").classed("text-highlight", function (r, ri) { return ri === (d.x); });
            d3.selectAll(".colLabel").classed("text-highlight", function (c, ci) { return ci === (d.y); });
    
            d3.select("#tooltip")
                .style("left", (d3.event.pageX + 10) + "px")
                .style("top", (d3.event.pageY - 10) + "px")
                .select("#value")
                .html("<p>Source: " + servers[d.x] + "</p>" + 
                      "<p>Dest: " + servers[d.y] + "</p>" +
                      "<p>RTT: " + (d.m_Item3 === undefined ? "N/A" : d.m_Item3 + "ns") + "</p>");
    
            //Show the tooltip
            d3.select("#tooltip").classed("hidden", false);
        })
        .on("mouseout", function () {
            d3.select(this).classed("cell-hover", false);
            d3.selectAll(".rowLabel").classed("text-highlight", false);
            d3.selectAll(".colLabel").classed("text-highlight", false);
            d3.select("#tooltip").classed("hidden", true);
        });
    
    // next, update the update section.
    heatmap.data(matrix);
    

1 个答案:

答案 0 :(得分:0)

好吧我让它工作但我不知道为什么,关键功能如何工作。 为了使其工作,我需要在连接数据时添加相同的键功能。

使用虚拟矩阵创建完整矩阵时:

Complex c = new Complex(3.72);

然后加入真实矩阵时:

.data(dummy, function (d) { return d.x + ":" + d.y; })

我仍然不知道什么是关键功能以及为什么它应该返回字符串?在SQL中加入时,键函数是否等于列名?如果key函数返回相同的字符串,则只会加入/更新数据?