在文本旁边的表中内联D3迷你图

时间:2014-09-10 20:00:23

标签: javascript d3.js

说是否有这样的表:

var data = [
    ['Orange', 'Orange', [6,3,3,2,5]],
    ['Apple', 'Red', [6,2,6,5,5]],
    ['Grape', 'Purple', [9,1,2,3,1]]
]

我希望字符串表示为字符串,但数字数组表示为D3折线图。如果它只是我关心的文字,我可以selectAll td元素并插入一些文字。

var tcells = trows
    .selectAll("td")
    .data(function(d, i) { return d; })
    .enter()
    .append("td")
    .text(function(d, i) { return d; });

第3列是文字,因此我想用图表更新它,或者添加另一列图表。说lines是一个创建折线图的函数,我想调用lines(),因为它会从每个行的第3列传递数据。

trows.selectAll("td")
    .data(function(d) {return d[2]}) // scope out data from 3rd column
    .enter()
    .append("td")
    //.call(lines([3,8,2,5,8,4])); // this works
    .call(lines);                // this doesn't

我的D3知识不稳定所以我不清楚数据和选择是如何通过的。

以下是完整代码: jsfiddle link

1 个答案:

答案 0 :(得分:1)

您将selection.call(func)方法与selection.each(func)方法混淆。

call是一种方便的方法,用于调用接受选择作为参数的函数。 trows.call(lines)等同于lines(trows),但它可以是方法链的一部分。

each用于为选择中的每个元素调用一次函数,将数据和索引作为参数传递。

至于为什么trows.call(lines([3,8,2,5,8,4]))"工作",它只是有点工作。您使用硬编码数据数组调用函数lines,但该函数不返回任何内容,因此选择本身没有call。 (如果您不了解其中的区别,可以find this answer useful。)

您的方法目前也只将线图附加到正文,它不会将其插入表格中。您有以下代码,您承认它们不起作用:

// dynamic selection doesn't
this.append("td").append('svg')
    .attr('width', width).attr('height', height)
    .append('path').attr('class','line')
    .datum(data).attr('d', line);

有几个原因导致失败:

  • 在您调用该函数的上下文中,直接调用lines([3,8,2,5,8,4])this值将不会被设置,因此将指向window对象;
  • 即使您使用each方法调用该函数(设置this值),this也会指向DOM节点,而不是您可以调用的选项d3方法;
  • 除了您的具体情况之外,它甚至不会指向DOM节点,因为您要从enter()选项中调用它,而您还没有添加新节点爱好。

总之,为了让事情顺利进行:

  1. 在主程序中,在创建新的each元素后,使用lines来调用<td>函数:

    trows.selectAll("td.graph")  
         //use a class so you don't re-select the existing <td> elements
      .data(function(d) {return [d[2]];})
         // the value returned by a data function must always be an array
         // containing data objects for each new element you create -- 
         // you only want one element containing the entire data array, 
         // not individual elements for each number, so wrap it in another array
      .enter()
        .append("td")
        .attr("class", "graph")
        .each(lines); 
    
  2. lines函数中,重新选择this元素(现在将指向刚刚创建的<td>),并将迷你线SVG附加到其中:

    d3.select(this).append('svg')
            .attr('width', width)
            .attr('height', height)
         .append('path')
            .attr('class','line')
            .datum(data)
            .attr('d', line);
    
  3. http://jsfiddle.net/Lgq6ct9f/9/
    (通过其他一些清理,所以你不会在主程序中间有一个功能定义)