1

nvd3 ブレット チャートをカスタマイズしましたが、正常に動作しています。ウィンドウのサイズが変更されると問題が発生し、chart.update ハンドラーがエラーd3.js:8868 Uncaught TypeError: Cannot read property '1' of undefinedを作成するため、コード コントロールはチャート関数を再度実行しません。助けてください。

// expected input data format
var config = {
  title: 'Sample Chart',
  subtitle: 'description subtitle',
  legend: true,
  min: 0,
  max: 500,
  averageText: 'Top Users in Intro Psychology courses nationally',
  data: [{
    label: 'Instructor1',
    marker: 20,
    color: ''
  }, {
    label: 'Instructor2',
    marker: 250,
    color: ''
  }, {
    label: 'Instructor3',
    marker: 150,
    color: ''
  }, {
    label: 'Instructor4',
    marker: 50,
    color: ''
  }]
};

// initializing the colors category
var colors = config.data.map(function(val) {
    return val.color
  }),
  defaultColors = d3.scale.category20().range();

// data initialization
function generateData() {
  var sum = new Number().valueOf();
  config.data.sort(function(val1, val2) {
    return val1.marker <= val2.marker;
  });
  config.data.forEach(function(val, i) {
    sum += Number(val.marker);
  });

  return {
    "ranges": [config.min, sum / config.data.length, config.max],
    "measures": [config.max],
    "markers": config.data.map(function(val) {
      return val.marker
    })
  };
}

// wrap the text within given width
function wrap(text, width) {
  var words = text.text().split(/\s+/),
    line = [],
    dy = parseFloat(text.attr("dy")) || 10,
    lineNumber = 0,
    lineHeight = 3;
  var tspan = text.text(null).append('tspan');
  var offset = 0;
  while (1) {
    if (tspan.node().getComputedTextLength() > width) {
      words.unshift(line.pop());
      tspan.text(line.join(' '));
      offset = (width - tspan.node().getComputedTextLength()) / 2;
      tspan.attr('x', offset);
      tspan = text.append('tspan').attr("dy", lineHeight + dy);
      line = [];
      ++lineNumber;
    } else {
      if (!words.length)
        break;
      line.push(words.shift());
      tspan.text(line.join(' '));
      offset = (width - tspan.node().getComputedTextLength()) / 2;
      tspan.attr('x', offset);
    }
  }
  text.attr('y', -1 * lineNumber * lineHeight * 5);
}

// set the position for markers
function setMarkers(markers) {
    markers.each(function(mark, i) {
      var marker = d3.select(this);
      marker.attr('d', 'M -5 -10 l0 20 l5 5 l5 -5 l0 -20 z')
        .style({
          'fill': colors[i] || defaultColors[i],
          'stroke': 'none'
        });
    });
  }
  //convert r,g,b to hex value

function rgb2hex(rgb) {
  rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
  return (rgb && rgb.length === 4) ? "#" +
    ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
    ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +
    ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
}

// handle tooltip events
function setTooltipEvents(chart) {
  chart.bullet.dispatch.on('elementMouseover.tooltip', function(evt) {
    if (evt.label === 'Current') {
      return false;
    }
    var thisBullet = config.data.filter(function(val, i) {
      return (rgb2hex(evt.color) == (val.color || defaultColors[i]) && evt.value === val.marker);
    })[0];
    evt['series'] = {
      key: thisBullet.label,
      value: evt.value,
      color: evt.color
    };

    chart.tooltip.data(evt).hidden(false);
  });
  d3.select('#chart #nv-avg').on('mouseover', function(evt) {
    evt['series'] = {
      key: 'Average',
      value: evt.ranges[1],
      color: defaultColors[defaultColors.length - 1]
    };

    chart.tooltip.data(evt).hidden(false);
  });

  d3.select('#chart #nv-avg').on('mousemove', function(evt) {
    chart.tooltip();
  });

  d3.select('#chart #nv-avg').on('mouseleave', function(evt) {
    chart.tooltip.hidden(true);
  });
}

// core graph/chart drawing snippet 
nv.addGraph(function() {
  var chart = nv.models.bulletChart() // initialize the chart
    .margin({
      right: 10,
      left: 10
    })
    .tickFormat(function(d) {
      return d + "%";
    });

  d3.select('#chart svg') //setup chart svg container
    .datum(generateData())
    .transition().duration(1000)
    .style({
      'height': '400px'
    })
    .call(chart);

  var width = nv.utils.availableWidth(null, d3.select('#chart svg'), chart._options.margin);

  var scaleBar = d3.select('.nv-measure') // style for main axis
    .style({
      'fill': '#000',
      'height': '5'
    });
  var parentBox = d3.select(scaleBar.node().parentNode); // wrapper for main axis
  var avgRange = d3.select('.nv-rangeAvg').node(); // average marker node 
  var avgBox = avgRange.getBBox(); // average marker dimensions
  var scaleBarBox = scaleBar.node().getBBox(); // main axis dimensions

  d3.selectAll('.nv-range').remove(); // remove extra elements

  d3.select('.nv-bulletChart').attr('transform', function() {
    var transform = d3.transform(d3.select(this).attr("transform"));
    return 'translate(' + transform.translate[0] + ',' + 185 + ')';
  });
  // set average marker
  var avgRectWidth = 150,
    avgRectHeight = 50;
  var avgMarker = parentBox.append('g').attr({
    'transform': 'translate(' + (avgBox.x + avgBox.width - avgRectWidth / 2) + ',' + (-1 * (avgRectHeight - scaleBarBox.y)) + ')',
    'id': 'nv-avg'
  });

  var avgMarkerRect = avgMarker.append('rect')
    .attr({
      'width': avgRectWidth,
      'height': avgRectHeight,
      'x': 0,
      'y': 0,
      'fill': '#fff',
      'fill-opacity': 0
    });
  var avgMarkerBox = avgMarkerRect.node().getBBox();

  avgMarker.append('path')
    .attr({
      'transform': 'translate(' + (avgMarkerBox.x + avgMarkerBox.width / 2) + ',' + avgMarkerBox.height + ')',
      'd': 'M0 0 l7.5 -5 l0 -25 l-15 0 l0 25 z'
    }).style({
      'fill': defaultColors[defaultColors.length - 1],
      'stroke': 'none'
    });
  avgMarker.append('text').text(config.averageText).attr({
    'x': 0,
    'y': 0
  });

  d3.select('#nv-avg text').call(wrap, avgMarkerBox.width);

  // left end circle
  parentBox.append('circle').attr({
    'cx': scaleBarBox.x,
    'cy': scaleBarBox.y + scaleBarBox.height / 2,
    'r': '10'
  });

  //right end circle
  parentBox.append('circle').attr({
    'cx': scaleBarBox.x + scaleBarBox.width,
    'cy': scaleBarBox.y + scaleBarBox.height / 2,
    'r': '10'
  });

  // set markers for data to be plotted
  d3.select('#chart').selectAll('.nv-markerTriangle')
    .call(setMarkers);

  //optional functionality to format ticks
  d3.selectAll('#chart .nv-tick').each(function(tick, i) {
    var text = d3.select(this).select('text');
    if (i % 2 !== 0)
      text.text('');
  });

  setTooltipEvents(chart);

  nv.utils.windowResize(function() {

    chart.update();
    width = nv.utils.availableWidth(null, d3.select('#chart svg'), chart._options.margin);

  }); // update chart on resize
  return chart;
});
<html>

<head>
  <link data-require="nvd3@*" data-semver="1.8.1" rel="stylesheet" href="https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.css" />
  <link data-require="bootstrap-css@*" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  <script data-require="nvd3@*" data-semver="1.8.1" src="https://cdn.rawgit.com/novus/nvd3/v1.8.1/build/nv.d3.js"></script>
  <script type="text/javascript.js"></script>
</head>

<body>
  <div id="chart" class="container" style="position: relative;top: 50px;">
    <svg></svg>
  </div>
</body>

</html>

4

1 に答える 1

0

今日同じ問題に直面しましたが、これは NVD3 ライブラリのバグです。

于 2016-06-30T21:05:09.730 に答える