使用d3.js在表中显示两个字符串

时间:2014-01-02 01:38:50

标签: d3.js

我一直在尝试使用d3.js来显示一个使用两个输入字符串的表,我已添加下面的代码。显示第二个字符串时,仅显示索引大于字符串x长度的字符。

我认为这是与匿名函数相关的东西,当迭代第二个字符串时,我从它在第一个字符串中完成的索引值开始,例如,仅从第二个字符串而不是“fresihnfo”显示“fo” ”。谁能给我一些关于如何解决这个问题的指示?

谢谢!

        var x = ["a", "e", "d", "i", "r", "z"];
        var y = ["f", "r", "s", "i", "h", "n", "f", "o"];

        var w = (x.length + 1) * 50;
        var h = (y.length + 1) * 50;

        var svg = d3.select("body")
                    .append("svg")
                    .attr("width", w)
                    .attr("height", h);

        /*Displays the first string*/
        svg.selectAll("rect")
           .data(x)
           .enter()
           .append("rect")
           .attr("x", function(d, i) {
                return (i * 45) + 45;
           })
           .attr("y", "0px")
           .attr("width", "40px")
           .attr("height", "40px")
           .attr("fill", "rgb(0, 0, 102)");

        svg.selectAll("text")
           .data(x)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("text-anchor", "middle")
           .attr("x", function(d, i) {
                return (i * 45) + 65;
           })
           .attr("y", "27px")
           .attr("font-family", "sans-serif")
           .attr("font-size", "20px")
           .attr("fill", "white");

        /*Displays the second string*/
        svg.selectAll("rect")
           .data(y)
           .enter()
           .append("rect")
           .attr("x", "0px")
           .attr("y", function(d, i) {
                return ((i - x.length) * 45) + 45;
           })
           .attr("width", "40px")
           .attr("height", "40px")
           .attr("fill", "rgb(0, 0, 102)");

        svg.selectAll("text")
           .data(y)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("text-anchor", "middle")
           .attr("x", "20px")
           .attr("y", function(d, i) {
                return ((i - x.length) * 45) + 70;
           })
           .attr("font-family", "sans-serif")
           .attr("font-size", "20px")
           .attr("fill", "white");          

当前输出:

co

所需的输出将是左列中显示字符串y的其余部分。

2 个答案:

答案 0 :(得分:2)

正如Marc所说,问题在于您的每次第二次选择都被解释为第一次选择的更新,而不是一组新的元素。由于您只处理更新的enter()部分,因此您甚至看不到已更改第一组矩形数据的事实。

要确认第一组矩形已从第二个数组中获取数据,请右键单击一个,选择“检查元素”,然后在检查器中打开属性选项卡 - __data__ property保存元素的D3数据对象。

那么你如何解决它?您需要一种在select语句中区分两组矩形的方法。有两种选择:

选项1:在SVG组元素上使用子选择(<g>

你有两组矩形,所以使用svg分组元素来保持它们的组织是有意义的。不是将矩形直接添加到svg,而是将一个组元素添加到svg,然后将矩形/文本添加到它。

svg.append("g").selectAll("rect") //etc.

对第二组矩形执行相同操作,并且它们都将很好地排列在第二组中,只要总是从组选择中调用select语句,它将只选择属于该组的元素基。

选项2:使用class属性区分两种元素类型

您有两种类型的值,x和y,因此您应该通过设置相应的类属性来区分svg元素属于哪种类型。然后,在select语句中,确保只选择正确类的元素。某个类的元素的CSS selector格式为elementName.ClassName,因此您的代码如下所示:

.selectAll("rect.x")
  .data(x)
enter()
  .append("rect")
  .classed("x", true)
  // etc. 

选项3:同时使用

如果您将来想要更新矩形,只需将它们分成两组就不够了 - 您还需要一种方法来区分这些组。因此,在附加<g>元素时添加x或y类,并在创建时使用"g.x""g.y"选择器。

如果您想保持D3代码的正确性,我强烈建议您阅读选择,选择器,嵌套选择和更新过程。有list of tutorials on the wiki

P.S。 您创建的i值作为匿名函数的命名参数始终受限于该函数的范围。如果需要,可以给它们不同的名称,它们的值将始终是D3传递给它们的值 - 第一个参数的数据对象,以及第二个参数的当前选择中的索引。

答案 1 :(得分:0)

selectAll()的主要目标是在使用data()

时选择容器中的现有元素

它会将数据与元素连接起来,所以我们可以

使用enter()为新数据项添加新元素;

使用update()更新与数据匹配的元素。

使用exit()删除没有数据匹配的元素

当你使用svg.selectAll("rect").data(x).enter()追加rect时,selectAll()将返回0元素

data(x).enter()将为每个数据生成占位符,以便您可以在x中追加所有数据

但是当使用svg.selectAll("rect").data(y).enter()为y添加rect时。 selectAll()将返回6

rects,所以data(y).enter()将产品占位符为'f'和'o'这就是为什么你只得到两个

元素

解决方案:对x和y使用不同的选择器,例如不同的类名

svg.selectAll(".x").data(x).enter().append("rect").attr("class", "x"); // other operation

svg.selectAll(".y").data(x).enter().append("rect").attr("class", "y"); // other operation

您可以通过这些文章深入了解d3选择和数据连接:

http://bost.ocks.org/mike/join/

http://bost.ocks.org/mike/selection/