Data binding d3.js:为什么不';我的柱状图中的列是否包含完整数据?

Data binding d3.js:为什么不';我的柱状图中的列是否包含完整数据?,data-binding,d3.js,Data Binding,D3.js,我使用的是一个稍加修改的可重用柱状图脚本 效果很好。然而,我只是尝试在hover上添加一些工具提示,这将显示JSON文件中每列的附加数据,但是附加数据不在那里。我查看检查器,只看到用于计算x和y的两个值。脚本的编写方式是否有明显的不绑定完整数据集的地方 脚本: function columnChart() { var margin = {top: 30, right: 10, bottom: 50, left: 50}, width = 420, height = 4

我使用的是一个稍加修改的可重用柱状图脚本

效果很好。然而,我只是尝试在hover上添加一些工具提示,这将显示JSON文件中每列的附加数据,但是附加数据不在那里。我查看检查器,只看到用于计算x和y的两个值。脚本的编写方式是否有明显的不绑定完整数据集的地方

脚本:

function columnChart() {
  var margin = {top: 30, right: 10, bottom: 50, left: 50},
      width = 420,
      height = 420,
      xRoundBands = 0.2,
      xValue = function(d) { return d[0]; },
      yValue = function(d) { return d[1]; },
      xScale = d3.scale.ordinal(),
      yScale = d3.scale.linear(),
      xFormat = '',
      yFormat = '',
      yAxis = d3.svg.axis().scale(yScale).orient("left"),
      xAxis = d3.svg.axis().scale(xScale);


  function chart(selection) {
    selection.each(function(data) {

      // Convert data to standard representation greedily;
      // this is needed for nondeterministic accessors.
      data = data.map(function(d, i) {
        return [xValue.call(data, d, i), yValue.call(data, d, i)];
      });

      // Update the x-scale.
      xScale
          .domain(data.map(function(d) { return d[0];} ))
          .rangeRoundBands([0, width - margin.left - margin.right], xRoundBands);


      // Update the y-scale.
      yScale
          .domain(d3.extent(data.map(function(d) { return d[1];} )))
          .range([height - margin.top - margin.bottom, 0])
          .nice();


      // Select the svg element, if it exists.
      var svg = d3.select(this).selectAll("svg").data([data]);

      // Otherwise, create the skeletal chart.
      var gEnter = svg.enter().append("svg").append("g");
      gEnter.append("g").attr("class", "bars");
      gEnter.append("g").attr("class", "y axis");
      gEnter.append("g").attr("class", "x axis");
      gEnter.append("g").attr("class", "x axis zero");

      // Update the outer dimensions.
      svg .attr("width", width)
          .attr("height", height);

      // Update the inner dimensions.
      var g = svg.select("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

     // Update the bars.
      var bar = svg.select(".bars").selectAll(".bar").data(data);
      bar.enter().append("rect");
      bar.exit().remove();
      bar.attr("class", function(d, i) { return d[1] < 0 ? "bar negative" : "bar positive"; })
        .attr("x", function(d) { return X(d); })
        .attr("y", function(d, i) { return d[1] < 0 ? Y0() : Y(d); })
        .attr("width", xScale.rangeBand())
        .attr("height", function(d, i) { return Math.abs( Y(d) - Y0() ); })
        .on("click", function(d, i) 
        {
            d3.selectAll('.bar').classed('fade', true);
            d3.select(this).classed("sel", true).classed("fade", false);
        })
        .on("mouseover", function(d, i) 
        {
            d3.select(this).classed("hover", true);
        })
        .on("mouseout", function(d, i) 
        {
            d3.select(this).classed("hover", false);
        });

    // x axis at the bottom of the chart
     g.select(".x.axis")
        .attr("transform", "translate(0," + (height - margin.top - margin.bottom) + ")")
        .call(xAxis.orient("bottom").tickFormat(xFormat));

    // zero line
     g.select(".x.axis.zero")
        .attr("transform", "translate(0," + Y0() + ")")
        .call(xAxis.tickFormat("").tickSize(0));


    // Update the y-axis.
    g.select(".y.axis")
        .call(yAxis);

    // Horizontal grid
    g.insert("g", ".bars")         
        .attr("class", "grid horizontal")
        .call(d3.svg.axis().scale(yScale)
            .orient("left")
            .tickSize(-(width-margin.left-margin.right), 0, 0)
            .tickFormat("")
        );

    });
  }


// The x-accessor for the path generator; xScale ∘ xValue.
  function X(d) {
    return xScale(d[0]);
  }

  function Y0() {
    return yScale(0);
  }

  // The x-accessor for the path generator; yScale ∘ yValue.
  function Y(d) {
    return yScale(d[1]);
  }

  chart.margin = function(_) {
    if (!arguments.length) return margin;
    margin = _;
    return chart;
  };

  chart.width = function(_) {
    if (!arguments.length) return width;
    width = _;
    return chart;
  };

  chart.height = function(_) {
    if (!arguments.length) return height;
    height = _;
    return chart;
  };

  chart.x = function(_) {
    if (!arguments.length) return xValue;
    xValue = _;
    return chart;
  };

  chart.y = function(_) {
    if (!arguments.length) return yValue;
    yValue = _;
    return chart;
  };

  chart.yTickFormat = function(_) {
    if (!arguments.length) return yFormat;
    yFormat = _;
    return chart;
  };

  chart.xTickFormat = function(_) {
    if (!arguments.length) return xFormat;
    xFormat = _;
    return chart;
  };

  return chart;
}
function renderGraph(view){
    var chartWidth = mainWidth();
    var chartHeight = 400;
    var parseDate = d3.time.format("%Y-%m-%d").parse;
    var xFormat = d3.time.format("%b %e");

    var data = [];
    var req = $.ajax({
        url: '/data/column-data.json',
        type: 'GET',
        dataType: 'json',
        success: function(response) {
            data = response;
        }
    });

    $.when(req).done(function() {

        d3.select("#columnChart")
          .datum(data.widgets)
            .call(columnChart()
              .width(chartWidth)
              .height(chartHeight)
              .x(function(d, i) { return parseDate(d[0]); })
              .xTickFormat(xFormat)
              .y(function(d, i) {
                var yData;
                if (view === 'thisView'){
                    yData = d[1];
                }else if (view === 'thatView'){
                    yData = d[2];
                }
                return yData;
              }));
    });
}
{ "widgets" : [
    ["2013-09-15", 1, 66622, 1, 3],
    ["2013-09-16", 0, 0, 0, 0],
    ["2013-09-17", 2, 76316, 2, 2],
    ["2013-09-18", 4, 291244, 8, 12],
    ["2013-09-19", 1, 74674, 2, 2],
    ["2013-09-20", 5, 287965, 7, 5],
    ["2013-09-21", 0, 0, 0, 0],
    ["2013-09-22", 0, 0, 0, 0],
    ["2013-09-23", 7, 459249, 15, 22],
    ["2013-09-24", 2, 317320, 1, 6],
    ["2013-09-25", 3, 100269, 3, 10],
    ["2013-09-26", 4, 181080, 8, 4],
    ["2013-09-27", 1, 38056, 1, 1],
    ["2013-09-28", 0, 0, 0, 0],
    ["2013-09-29", 0, 0, 0, 0],
    ["2013-09-30", 3, 449334, 2, 13],
    ["2013-10-01", 9, 403929, 5, 15],
    ["2013-10-02", 4, 222512, 7, 12],
    ["2013-10-03", 1, 196012, 3, 9],
    ["2013-10-04", 2, 391716, 2, 8],
    ["2013-10-05", 0, 0, 0, 0],
    ["2013-10-06", 0, 0, 0, 0],
    ["2013-10-07", 4, 260312, 8, 14],
    ["2013-10-08", 1, 34350, 1, 1],
    ["2013-10-09", 3, 179067, 9, 18],
    ["2013-10-10", 2, 124250, 8, 19],
    ["2013-10-11", 2, 381186, 4, 9],
    ["2013-10-12", 0, 0, 0, 0],
    ["2013-10-13", 0, 0, 0, 0],
    ["2013-10-14", 5, 393400, 11, 17]
    ]
}
数据如下所示:

function columnChart() {
  var margin = {top: 30, right: 10, bottom: 50, left: 50},
      width = 420,
      height = 420,
      xRoundBands = 0.2,
      xValue = function(d) { return d[0]; },
      yValue = function(d) { return d[1]; },
      xScale = d3.scale.ordinal(),
      yScale = d3.scale.linear(),
      xFormat = '',
      yFormat = '',
      yAxis = d3.svg.axis().scale(yScale).orient("left"),
      xAxis = d3.svg.axis().scale(xScale);


  function chart(selection) {
    selection.each(function(data) {

      // Convert data to standard representation greedily;
      // this is needed for nondeterministic accessors.
      data = data.map(function(d, i) {
        return [xValue.call(data, d, i), yValue.call(data, d, i)];
      });

      // Update the x-scale.
      xScale
          .domain(data.map(function(d) { return d[0];} ))
          .rangeRoundBands([0, width - margin.left - margin.right], xRoundBands);


      // Update the y-scale.
      yScale
          .domain(d3.extent(data.map(function(d) { return d[1];} )))
          .range([height - margin.top - margin.bottom, 0])
          .nice();


      // Select the svg element, if it exists.
      var svg = d3.select(this).selectAll("svg").data([data]);

      // Otherwise, create the skeletal chart.
      var gEnter = svg.enter().append("svg").append("g");
      gEnter.append("g").attr("class", "bars");
      gEnter.append("g").attr("class", "y axis");
      gEnter.append("g").attr("class", "x axis");
      gEnter.append("g").attr("class", "x axis zero");

      // Update the outer dimensions.
      svg .attr("width", width)
          .attr("height", height);

      // Update the inner dimensions.
      var g = svg.select("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

     // Update the bars.
      var bar = svg.select(".bars").selectAll(".bar").data(data);
      bar.enter().append("rect");
      bar.exit().remove();
      bar.attr("class", function(d, i) { return d[1] < 0 ? "bar negative" : "bar positive"; })
        .attr("x", function(d) { return X(d); })
        .attr("y", function(d, i) { return d[1] < 0 ? Y0() : Y(d); })
        .attr("width", xScale.rangeBand())
        .attr("height", function(d, i) { return Math.abs( Y(d) - Y0() ); })
        .on("click", function(d, i) 
        {
            d3.selectAll('.bar').classed('fade', true);
            d3.select(this).classed("sel", true).classed("fade", false);
        })
        .on("mouseover", function(d, i) 
        {
            d3.select(this).classed("hover", true);
        })
        .on("mouseout", function(d, i) 
        {
            d3.select(this).classed("hover", false);
        });

    // x axis at the bottom of the chart
     g.select(".x.axis")
        .attr("transform", "translate(0," + (height - margin.top - margin.bottom) + ")")
        .call(xAxis.orient("bottom").tickFormat(xFormat));

    // zero line
     g.select(".x.axis.zero")
        .attr("transform", "translate(0," + Y0() + ")")
        .call(xAxis.tickFormat("").tickSize(0));


    // Update the y-axis.
    g.select(".y.axis")
        .call(yAxis);

    // Horizontal grid
    g.insert("g", ".bars")         
        .attr("class", "grid horizontal")
        .call(d3.svg.axis().scale(yScale)
            .orient("left")
            .tickSize(-(width-margin.left-margin.right), 0, 0)
            .tickFormat("")
        );

    });
  }


// The x-accessor for the path generator; xScale ∘ xValue.
  function X(d) {
    return xScale(d[0]);
  }

  function Y0() {
    return yScale(0);
  }

  // The x-accessor for the path generator; yScale ∘ yValue.
  function Y(d) {
    return yScale(d[1]);
  }

  chart.margin = function(_) {
    if (!arguments.length) return margin;
    margin = _;
    return chart;
  };

  chart.width = function(_) {
    if (!arguments.length) return width;
    width = _;
    return chart;
  };

  chart.height = function(_) {
    if (!arguments.length) return height;
    height = _;
    return chart;
  };

  chart.x = function(_) {
    if (!arguments.length) return xValue;
    xValue = _;
    return chart;
  };

  chart.y = function(_) {
    if (!arguments.length) return yValue;
    yValue = _;
    return chart;
  };

  chart.yTickFormat = function(_) {
    if (!arguments.length) return yFormat;
    yFormat = _;
    return chart;
  };

  chart.xTickFormat = function(_) {
    if (!arguments.length) return xFormat;
    xFormat = _;
    return chart;
  };

  return chart;
}
function renderGraph(view){
    var chartWidth = mainWidth();
    var chartHeight = 400;
    var parseDate = d3.time.format("%Y-%m-%d").parse;
    var xFormat = d3.time.format("%b %e");

    var data = [];
    var req = $.ajax({
        url: '/data/column-data.json',
        type: 'GET',
        dataType: 'json',
        success: function(response) {
            data = response;
        }
    });

    $.when(req).done(function() {

        d3.select("#columnChart")
          .datum(data.widgets)
            .call(columnChart()
              .width(chartWidth)
              .height(chartHeight)
              .x(function(d, i) { return parseDate(d[0]); })
              .xTickFormat(xFormat)
              .y(function(d, i) {
                var yData;
                if (view === 'thisView'){
                    yData = d[1];
                }else if (view === 'thatView'){
                    yData = d[2];
                }
                return yData;
              }));
    });
}
{ "widgets" : [
    ["2013-09-15", 1, 66622, 1, 3],
    ["2013-09-16", 0, 0, 0, 0],
    ["2013-09-17", 2, 76316, 2, 2],
    ["2013-09-18", 4, 291244, 8, 12],
    ["2013-09-19", 1, 74674, 2, 2],
    ["2013-09-20", 5, 287965, 7, 5],
    ["2013-09-21", 0, 0, 0, 0],
    ["2013-09-22", 0, 0, 0, 0],
    ["2013-09-23", 7, 459249, 15, 22],
    ["2013-09-24", 2, 317320, 1, 6],
    ["2013-09-25", 3, 100269, 3, 10],
    ["2013-09-26", 4, 181080, 8, 4],
    ["2013-09-27", 1, 38056, 1, 1],
    ["2013-09-28", 0, 0, 0, 0],
    ["2013-09-29", 0, 0, 0, 0],
    ["2013-09-30", 3, 449334, 2, 13],
    ["2013-10-01", 9, 403929, 5, 15],
    ["2013-10-02", 4, 222512, 7, 12],
    ["2013-10-03", 1, 196012, 3, 9],
    ["2013-10-04", 2, 391716, 2, 8],
    ["2013-10-05", 0, 0, 0, 0],
    ["2013-10-06", 0, 0, 0, 0],
    ["2013-10-07", 4, 260312, 8, 14],
    ["2013-10-08", 1, 34350, 1, 1],
    ["2013-10-09", 3, 179067, 9, 18],
    ["2013-10-10", 2, 124250, 8, 19],
    ["2013-10-11", 2, 381186, 4, 9],
    ["2013-10-12", 0, 0, 0, 0],
    ["2013-10-13", 0, 0, 0, 0],
    ["2013-10-14", 5, 393400, 11, 17]
    ]
}
工具提示应显示任意一列的完整数据。web检查器为每列显示一个2的数组(我希望是5的数组)

如何修改脚本以绑定每列的完整数据?

谢谢

更新: 我仍然没有解决这个问题,尽管@adam pearce离我很近。我已经准备了几个jsbin来帮忙

原始脚本的bin位于此处:

下面是亚当回答的剧本:

这只是注释了以下内容:

      //data = data.map(function(d, i) {
      //  return [xValue.call(data, d, i), yValue.call(data, d, i)];
      //});
在第二个示例中,您可以看到x轴和y轴都无法渲染,尽管我想要的完整数据集绑定到每个条。web检查器显示以下错误:

'undefined' is not a function (evaluating 'd.getMonth()')" which points to line 8410 in d3.v3.js, in d3_time_formats.
如何修改此脚本以在不中断轴的情况下获取完整数据?

  data = data.map(function(d, i) {
    return [xValue.call(data, d, i), yValue.call(data, d, i)];
  });
数据中删除除前两列以外的所有内容。查看代码,我认为如果您注释掉这三行代码,它仍然可以工作

回应您的评论:

// x axis at the bottom of the chart
 g.select(".x.axis")
    .attr("transform", "translate(0," + (height - margin.top - margin.bottom) + ")")
    .call(xAxis.orient("bottom"));//.tickFormat(xFormat));

您试图将字符串打印为日期,如果不先解析字符串,则无法执行此操作。

谢谢@adam pearce!一个快速的试验表明,这几乎是正确的!它确实绑定了完整的数据。一个小问题是它破坏了轴心。快速查看告诉我,如果不进行进一步编辑,我可能需要在数据的前两列中包含x和y的值(因此注释“这是非确定性访问器所需的”)这可能不起作用,因此我必须查看其他修改。如此接近…因此两个轴都没有显示,并且看起来它可能在x轴上断开。我得到以下错误:“'undefined'不是一个函数(计算'd.getMonth()')”,它指向d3.v3.js中的第8410行,采用d3_time_格式。可能与xFormat有关吗?