javascript - 无法读取未定义的属性 "0"

标签 javascript d3.js

我有一个如下所示的 div 标签。

<div id="line_chart" ></div>

然后在脚本标签内使用 d3 代码来绘制图表。

      var data = [{ "date": "2016.07.28", "close": 186889.45 }, { "date": 
      "2016.07.29", "close": 187156.54 }, { "date": "2016.08.01", "close": 
       187218.54 }, { "date": "2016.08.02", "close": 187624.73 }, { "date": 
       "2016.08.03", "close": 187198.72 }, { "date": "2016.08.05", "close": 
       185673.17 }, { "date": "2016.08.11", "close": 188383.55 }, { "date": 
       "2016.08.12", "close": 188033.59 }, { "date": "2016.08.13", "close": 
       187877.45 }, { "date": "2016.08.14", "close": 187877.45 }, { "date": 
       "2016.08.15", "close": 187935.9 }, { "date": "2016.08.16", "close": 
       180575.62 }, { "date": "2016.08.17", "close": 181022.03 }, { "date": 
       "2016.08.18", "close": 180294.82 }, { "date": "2016.08.19", "close": 
       194423.11 }];

            margin = {
                top: 20,
                right: 20,
                bottom: 20,
                left: 100
            };
            var width = 960,
                        height = 500;

            var vis = d3.select("#line_chart").append("svg")
                                .attr("width", width + margin.left + 
                                  margin.right)
                                .attr("height", height + margin.top + 
                                  margin.bottom);


            var parseTime = d3.time.format("%Y.%m.%d").parse;

            max_y = 0;
            min_y = data[0].close;
            var extent = d3.extent(data.map(function (d) { return d.date }))

            max_x = extent[1];
            min = extent[0];

            for (i = 0; i < data.length; i++) {
                max_y = Math.max(max_y, data[i].close);
                min_y = Math.min(min_y, data[i].close);
            }

            var x = d3.time.scale()
             .rangeRound([margin.left, width]);


            xScale = x.domain(d3.extent(data, function (d) {
                return parseTime(d.date);
            }));


            yScale = d3.scale.linear().range([height - margin.top, margin.bottom]).domain([min_y, max_y]),

            xAxis = d3.svg.axis()
            .scale(xScale),

            yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("left");


            vis.append("svg:g")                
                .attr("class", "x axis")
                .style({ 'stroke': 'Black', 'fill': 'none', 'stroke-width': '1px' })
                .attr("transform", "translate(0," + (height - margin.bottom) + ")")                   
                .call(xAxis);


            vis.append("svg:g")                  
                .attr("class", "y axis")
                .style({ 'stroke': 'Black', 'fill': 'none', 'stroke-width': '1px' })
                .attr("transform", "translate(" + (margin.left) + ",0)")                    
                .call(yAxis);

            var line = d3.svg.line()
                 .x(function (d) {
                     return xScale(parseTime(d.date));
                 })
                 .y(function (d) {
                     return yScale(d.close);
                 })
                 .interpolate("basis");              

            vis.append('svg:path')
              .datum(data)
              .attr("fill", "none")
              .attr("stroke", "steelblue")
              .attr("stroke-linejoin", "round")
              .attr("stroke-linecap", "round")
              .attr("stroke-width", 1.5)
              .attr("d", line);


            var hoverLineGroup = vis.append("g")
                                .attr("class", "hover-line");

            var hoverLine = hoverLineGroup
                .append("line")
                    .attr("stroke", "#000")
                    .attr("x1", 10).attr("x2", 10)
                    .attr("y1", 0).attr("y2", height);

            var hoverTT = hoverLineGroup.append('text')
               .attr("class", "hover-tex capo")
               .attr('dy', "0.35em");

            var cle = hoverLineGroup.append("circle")
                .attr("r", 4.5);

            var hoverTT2 = hoverLineGroup.append('text')

               .attr("class", "hover-text capo")
               .attr('dy', "0.55em");

            hoverLineGroup.style("opacity", 1e-6);

            var rectHover = vis.append("rect")
              .data(data)
              .attr("fill", "none")
              .attr("class", "overlay")
              .attr("width", width)
              .attr("height", height);

            vis
                .on("mouseout", hoverMouseOff)
                .on("mousemove", hoverMouseOn);


            var bisectDate = d3.bisector(function (d) { return 
              parseTime(d.date); }).left;

            function hoverMouseOn() {

                var mouse_x = d3.mouse(this)[0];
                var mouse_y = d3.mouse(this)[1];
                var graph_y = yScale.invert(mouse_y);
                var graph_x = xScale.invert(mouse_x);

                var mouseDate = xScale.invert(mouse_x);
                var i = bisectDate(data, mouseDate);

                var d0 = data[i - 1]
                var d1 = data[i];

                var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;

                hoverTT.text("Date: " + d.date);                 
                hoverTT.attr('x', mouse_x);
                hoverTT.attr('y', yScale(d.close));


                hoverTT2.text("Portfolio Value: " + Math.round(d.close * 
             100) / 100)
                   .attr('x', mouse_x)
                   .attr('y', yScale(d.close) + 10);

                cle
                  .attr('x', mouse_x)
                  .attr('y', mouse_y);


                hoverLine.attr("x1", mouse_x).attr("x2", mouse_x)
                hoverLineGroup.style({ 'font-weight': 'bold', 'opacity': 1 
             });


            }

            function hoverMouseOff() {
                hoverLineGroup.style("opacity", 1e-6);
            }

图表是按照我想要的方式绘制的。没关系。 但是当我打开 javascript 控制台(ctrl + shift + J)时出现几个错误。

 Uncaught ReferenceError: radOnResponseEnd is not defined
 Uncaught TypeError: Cannot read property '0' of undefined
 .
 .
 .

我认为这些错误是由于hoverMouseOn方法造成的。 以下行是可疑的

var bisectDate = d3.bisector(function (d) { return parseTime(d.date); 
 }).left;

因为bisectDate在函数hoverMouseOn()内部使用,该函数将数组“data”与bisectDate一起使用。看起来“数据”是空的,这就是为什么它说“无法读取未定义的属性“0””。

最佳答案

你的问题出在这里:

var bisectDate = d3.bisector(function(d) {
    return
    parseTime(d.date);
}).left;

在 JavaScript 中,当您在 return 之后添加新行时...

return
foo;

...您将不会返回foo。这与以下内容相同:

return;
foo;

因此,您没有返回任何内容(或未定义)。

解决方案:

它必须是:

var bisectDate = d3.bisector(function(d) {
    return parseTime(d.date);
}).left;

这是经过更改的代码:

  var data = [{
    "date": "2016.07.28",
    "close": 186889.45
  }, {
    "date": "2016.07.29",
    "close": 187156.54
  }, {
    "date": "2016.08.01",
    "close": 187218.54
  }, {
    "date": "2016.08.02",
    "close": 187624.73
  }, {
    "date": "2016.08.03",
    "close": 187198.72
  }, {
    "date": "2016.08.05",
    "close": 185673.17
  }, {
    "date": "2016.08.11",
    "close": 188383.55
  }, {
    "date": "2016.08.12",
    "close": 188033.59
  }, {
    "date": "2016.08.13",
    "close": 187877.45
  }, {
    "date": "2016.08.14",
    "close": 187877.45
  }, {
    "date": "2016.08.15",
    "close": 187935.9
  }, {
    "date": "2016.08.16",
    "close": 180575.62
  }, {
    "date": "2016.08.17",
    "close": 181022.03
  }, {
    "date": "2016.08.18",
    "close": 180294.82
  }, {
    "date": "2016.08.19",
    "close": 194423.11
  }];

  margin = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 100
  };
  var width = 960,
    height = 500;

  var vis = d3.select("body").append("svg")
    .attr("width", width + margin.left +
      margin.right)
    .attr("height", height + margin.top +
      margin.bottom);


  var parseTime = d3.time.format("%Y.%m.%d").parse;

  max_y = 0;
  min_y = data[0].close;
  var extent = d3.extent(data.map(function(d) {
    return d.date
  }))

  max_x = extent[1];
  min = extent[0];

  for (i = 0; i < data.length; i++) {
    max_y = Math.max(max_y, data[i].close);
    min_y = Math.min(min_y, data[i].close);
  }

  var x = d3.time.scale()
    .rangeRound([margin.left, width]);


  xScale = x.domain(d3.extent(data, function(d) {
    return parseTime(d.date);
  }));


  yScale = d3.scale.linear().range([height - margin.top, margin.bottom]).domain([min_y, max_y]),

    xAxis = d3.svg.axis()
    .scale(xScale),

    yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left");


  vis.append("svg:g")
    .attr("class", "x axis")
    .style({
      'stroke': 'Black',
      'fill': 'none',
      'stroke-width': '1px'
    })
    .attr("transform", "translate(0," + (height - margin.bottom) + ")")
    .call(xAxis);


  vis.append("svg:g")
    .attr("class", "y axis")
    .style({
      'stroke': 'Black',
      'fill': 'none',
      'stroke-width': '1px'
    })
    .attr("transform", "translate(" + (margin.left) + ",0)")
    .call(yAxis);

  var line = d3.svg.line()
    .x(function(d) {
      return xScale(parseTime(d.date));
    })
    .y(function(d) {
      return yScale(d.close);
    })
    .interpolate("basis");

  vis.append('svg:path')
    .datum(data)
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-linejoin", "round")
    .attr("stroke-linecap", "round")
    .attr("stroke-width", 1.5)
    .attr("d", line);


  var hoverLineGroup = vis.append("g")
    .attr("class", "hover-line");

  var hoverLine = hoverLineGroup
    .append("line")
    .attr("stroke", "#000")
    .attr("x1", 10).attr("x2", 10)
    .attr("y1", 0).attr("y2", height);

  var hoverTT = hoverLineGroup.append('text')
    .attr("class", "hover-tex capo")
    .attr('dy', "0.35em");

  var cle = hoverLineGroup.append("circle")
    .attr("r", 4.5);

  var hoverTT2 = hoverLineGroup.append('text')

  .attr("class", "hover-text capo")
    .attr('dy', "0.55em");

  hoverLineGroup.style("opacity", 1e-6);

  var rectHover = vis.append("rect")
    .data(data)
    .attr("fill", "none")
    .attr("class", "overlay")
    .attr("width", width)
    .attr("height", height);

  vis
    .on("mouseout", hoverMouseOff)
    .on("mousemove", hoverMouseOn);


  var bisectDate = d3.bisector(function(d) {
    return parseTime(d.date);
  }).left;

  function hoverMouseOn() {

    var mouse_x = d3.mouse(this)[0];
    var mouse_y = d3.mouse(this)[1];
    var graph_y = yScale.invert(mouse_y);
    var graph_x = xScale.invert(mouse_x);

    var mouseDate = xScale.invert(mouse_x);
    var i = bisectDate(data, mouseDate);

    var d0 = data[i - 1] ? data[i - 1] : 0;
    var d1 = data[i] ? data[i] : 0;

    var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;

    hoverTT.text("Date: " + d.date);
    hoverTT.attr('x', mouse_x);
    hoverTT.attr('y', yScale(d.close));


    hoverTT2.text("Portfolio Value: " + Math.round(d.close *
        100) / 100)
      .attr('x', mouse_x)
      .attr('y', yScale(d.close) + 10);

    cle
      .attr('cx', mouse_x)
      .attr('cy', mouse_y);


    hoverLine.attr("x1", mouse_x).attr("x2", mouse_x)
    hoverLineGroup.style({
      'font-weight': 'bold',
      'opacity': 1
    });


  }

  function hoverMouseOff() {
    hoverLineGroup.style("opacity", 1e-6);
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

PS:请注意 var d0 = data[i - 1];var d1 = data[i];。它们在图表的边缘处将是未定义

关于javascript - 无法读取未定义的属性 "0",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45272459/

相关文章:

javascript - 更新后如何将函数传递给 SetState 回调? ( react )

javascript - 是否可以将一大块 JS 存储在变量中?

javascript - 在 D3 js 图上绘制额外的线性数据

javascript - D3.js - 动态改变序数比例

javascript - 在react-redux中异步函数成功后如何调用组件的方法?

javascript - 不同数组上的map()结果不同

javascript - D3如何更新文字?

javascript - d3js 绘制 svg 矩形和线条问题

javascript - 如何在 d3 工具提示的 html 元素中使用 Angularjs 过滤器?

javascript - jQuery 1.9.1 没有方法实时错误