工具提示上的饼图悬停在多条形图 nvd3 上

Pie chart on tooltip hover on multi bar chart nvd3

我们能否使用 nvd3 在条形图中的工具提示悬停中显示不同的图形,例如饼图?

这是一个正在做这项工作的示例。这种方法背后的逻辑如下:

  • 禁用默认工具提示
  • 准备将用作工具提示的辅助图表(示例中的圆环图)
  • 在主图表(条形图)的回调中对条形元素注册事件监听器
    • mousemove - 显示和定位自定义圆环图工具提示
    • mouseleave - 隐藏工具提示

var donutContainer = document.getElementById('donut-chart');
var chartDonut;
var chartBar;

nv.addGraph(function() {

  chartBar = nv.models.discreteBarChart()
    .x(d => d.label)
    .y(d => d.value)
    .margin({left: 80}) 
    .showValues(true)
    .duration(250);

  // Disable the default tooltip 
  chartBar.tooltip.enabled(false);

  d3.select('#main-chart svg')
    .datum(historicalBarChart)
    .call(chartBar);

  nv.utils.windowResize(chartBar.update);

  return chartBar;
}, () => {

  // After the chart is loaded register some listeners
  // to determine when to show/hide the custom tooltip chart
  var bars = d3.selectAll('.nv-bar');
  bars.on('mousemove', function(bar) {
    
    // When the mouse is moved across bar
    // show the tooltip chart and update tooltip position
    d3.select('#donut-chart svg')
      .datum(bar.details)
      .call(chartDonut);

    nv.utils.windowResize(chartDonut.update);

    var e = window.event;
    donutContainer.style.display = 'block';
    donutContainer.style.left = e.clientX + "px";
    donutContainer.style.top = e.clientY - 50 + "px";
  });

  // When the mouse leaves a bar then hide the tooltip
  bars.on('mouseleave', e => donutContainer.style.display = 'none');
});

// Prepare the donut chart for the tooltip
nv.addGraph(function() {

  // Note here that duration(0) is used. This is done
  // because when you move the cursor between bars with different 
  // child group count( e.g. OS and Shoes) error is thrown
  chartDonut = nv.models.pieChart()
    .x(d => d.name)
    .y(d => d.value)
    .width(150)
    .height(150)
    .donut(true)
    .duration(0)
    .showLegend(false);

  chartDonut.tooltip.enabled(false);

  return chartDonut;
});

// Sample data
const historicalBarChart = [{
  key: 'Cumulative Return',
  values: [{
    label: 'Cars',
    value: 1500000,
    details: [{
      name: 'Audi',
      value: 500000
    }, {
      name: 'Mercedes',
      value: 700000
    }, {
      name: 'Ford',
      value: 300000
    }]
  }, {
    label: 'Mobile',
    value: 1000000,
    details: [{
      name: 'iPhone',
      value: 500000
    }, {
      name: 'Samsung',
      value: 410000
    }, {
      name: 'Lenovo',
      value: 90000
    }]
  }, {
    label: 'OS',
    value: 1500000,
    details: [{
      name: 'OSX',
      value: 500000
    }, {
      name: 'Windows',
      value: 500000
    }, {
      name: 'Linux',
      value: 500000
    }]
  }, {
    label: 'Shoes',
    value: 1400000,
    details: [{
      name: 'Addidas',
      value: 500000
    }, {
      name: 'Nike',
      value: 500000
    }, {
      name: 'Puma',
      value: 100000
    }, {
      name: 'Something',
      value: 300000
    }]
  }]
}];
text {
  font: 12px sans-serif;
}

svg {
  display: block;
}

html,
body,
#main-chart,
svg {
  height: 100%;
  width: 400px;
}

#donut-chart {
  position: absolute;
  height: 150px;
  width: 150px;
  background-color: white;
  z-index: 1;
  pointer-events: none;
  display: none;
  border: 1px solid black;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.js"></script>

<div id="main-chart"> <svg></svg></div>
<div id="donut-chart"><svg></svg></div>