每个系列都有独立工具提示的同步图表

时间:2019-03-29 09:48:15

标签: javascript highcharts

来自:stackoverflow.com/questions/42529308/synchronized-highcharts-does-not-work-when-charts-have-different-width,由morganfree建议。

当我使用共享工具提示时,上面的小提琴示例起作用了,但是我想要的是第二个图表具有两个或多个序列,而图表中的每个序列都需要有自己的工具提示。注意:使用上面的小提琴示例代码时,我可以同步工具提示,但是无法使用光标在第二张图表的系列之间切换。

任何帮助将不胜感激。

/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/

function highlightPoints(e) {
  const container = this;
  const charts = Highcharts.charts.slice();
  const chartIndex = charts.findIndex(chart => chart.renderTo === container);

  if (chartIndex > -1) {
    const chart = charts.splice(chartIndex, 1)[0];

    const event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
    const point = chart.series[0].searchPoint(event, true); // Get the hovered point

    if (point) {
      const x = point.x;
      point.highlight(e);

      charts.forEach(chart => {
        const caughtPoints = [];

        chart.series.forEach(series => {
          const points = series.points;
          for (let i = 0; i < points.length; i = i + 1) {
            if (points[i].x === x) {
              points[i].highlight(e);
              caughtPoints.push(points[i]);
              break;
            }
          }
        })
        chart.tooltip.refresh(caughtPoints); // Show the tooltip
      })
    }
  }
}



/**
 * Override the reset function, we don't need to hide the tooltips and crosshairs.
 */
Highcharts.Pointer.prototype.reset = function() {
  return undefined;
};

/**
 * Highlight a point by showing tooltip, setting hover state and draw crosshair
 */
Highcharts.Point.prototype.highlight = function(event) {
  this.onMouseOver(); // Show the hover marker
  this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};

/**
 * Synchronize zooming through the setExtremes event handler.
 */
function syncExtremes(e) {
  var thisChart = this.chart;

  if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
    Highcharts.each(Highcharts.charts, function(chart) {
      if (chart !== thisChart) {
        if (chart.xAxis[0].setExtremes) { // It is null while updating
          chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
            trigger: 'syncExtremes'
          });
        }
      }
    });
  }
}

// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function(activity) {
  $.each(activity.datasets, function(i, dataset) {

    // Add X values
    dataset.data = Highcharts.map(dataset.data, function(val, j) {
      return [activity.xData[j], val];
    });

    let additionalData;
    if (i === 1) {
      additionalData = dataset.data.map(v => [v[0], v[1] - 50]);
    }

    const options = {
      chart: {
        marginLeft: 40, // Keep all charts left aligned
        spacingTop: 20,
        spacingBottom: 20
      },
      title: {
        text: dataset.name,
        align: 'left',
        margin: 0,
        x: 30
      },
      credits: {
        enabled: false
      },
      legend: {
        enabled: false
      },
      xAxis: {
        crosshair: true,
        events: {
          setExtremes: syncExtremes
        },
        labels: {
          format: '{value} km'
        }
      },
      yAxis: {
        title: {
          text: null
        }
      },
      tooltip: {
        shared: true,
        positioner: function() {
          return {
            x: this.chart.chartWidth - this.label.width, // right aligned
            y: -1 // align to title
          };
        },
        borderWidth: 0,
        backgroundColor: 'none',
        pointFormat: '{point.y}',
        headerFormat: '',
        shadow: false,
        style: {
          fontSize: '18px'
        },
        valueDecimals: dataset.valueDecimals
      },
      series: [{
        data: dataset.data,
        name: dataset.name,
        type: dataset.type,
        color: Highcharts.getOptions().colors[i],
        fillOpacity: 0.3,
        tooltip: {
          valueSuffix: ' ' + dataset.unit
        }
      }]
    }

    if (i === 1) {
      options.series.push({
        data: additionalData,
        name: 'addit series',
        type: 'area',
        color: Highcharts.getOptions().colors[i],
        fillOpacity: 0.3,
        tooltip: {
          valueSuffix: ' ' + dataset.unit
        }
      })
    }

    $('<div class="chart-' + i + '">')
      .appendTo('#container')
      .highcharts(options);
  });

  /**
   * In order to synchronize tooltips and crosshairs, override the
   * built-in events with handlers defined on the parent element.
   */
  $('.chart-0, .chart-1, .chart-2').on('mousemove', highlightPoints);
});
.chart-0 {
  min-width: 320px;
  max-width: 800px;
  height: 220px;
  margin: 0 auto;
}

.chart-1 {
  min-width: 320px;
  max-width: 550px;
  height: 220px;
  margin: 0 auto;
}

.chart-2 {
  min-width: 300px;
  max-width: 300px;
  height: 220px;
  margin: 0 auto;
}

</style> <!-- http: //doc.jsfiddle.net/use/hacks.html#css-panel-hack -->
<meta name="viewport" content="width=device-width, initial-scale=1" /> <style>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>

<div id="container"></div>

1 个答案:

答案 0 :(得分:0)

您需要修改highlightPoints函数:

function highlightPoints(e) {
    const container = this;
    const charts = Highcharts.charts.slice();
    const chartIndex = charts.findIndex(chart => chart.renderTo === container);

    if (chartIndex > -1) {
        const chart = charts.splice(chartIndex, 1)[0];

        const event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
        const point = chart.series[0].searchPoint(event, true); // Get the hovered point

        if (point) {
            const x = point.x;

            charts.forEach(chart => {
                let caughtPoint;

                const points = chart.series[0].points;
                for (let i = 0; i < points.length; i = i + 1) {
                    if (points[i].x === x) {
                        points[i].highlight(e);
                        caughtPoint = points[i];
                        break;
                    }
                }
                chart.tooltip.refresh(caughtPoint); // Show the tooltip
            })
        }
    }
}

实时演示:http://jsfiddle.net/BlackLabel/tyazu4ko/