更改饼图标题取决于可见系列

时间:2017-09-05 14:40:57

标签: javascript jquery html css highcharts

我有2个系列的饼图。当两者都可见时,标题显示" Total"图表内的价值。并在悬停 - "详细"值。

现在,当系列中的一个不可见时,我需要显示"详细"标题而不是" Total"。

以下是一些演示:http://jsfiddle.net/jrvm4b6v/7/

我不知道如何展示"详细"禁用一个系列或启用两个系列后的值,导致legendItemClick我在点击之前收到状态...

$(document).ready(function() {

  Highcharts.chart('container', {
    chart: {
      plotBackgroundColor: null,
      plotBorderWidth: null,
      plotShadow: false,
      type: 'pie',
      borderRadius: 0,
      width: 1200,
      height: 250,
      backgroundColor: '#fff',
      marginTop: 0,
      marginRight: 950,
      spacingTop: 0,
      spacingBottom: 0,
      spacingLeft: 0,
      events: {
        load: function(event) {

          this.setTitle({
            text: generateChartText(true, this),
            x: -468,
            y: 124
          });
        }
      }
    },
    legend: {
      useHTML: true,
      layout: 'vertical',
      verticalAlign: 'top',
      x: 0,
      y: 40,
      itemMarginBottom: 30,
      labelFormatter: function() {
        var description = this.name === 'Direct' ? 'Customers who use Chrome' : 'Customers who use Firefox';

        return '<div class="img"></div><div><span>' + this.name + '</span><br>' + '<p style="font-size: 13px; color: #666666;">' + description + '</p>' + '</div>';
      }
    },
    title: {
      text: 'Browser market shares January, 2015 to May, 2015'
    },
    tooltip: {
      pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
    },
    plotOptions: {
      pie: {
        allowPointSelect: true,
        cursor: 'pointer',
        dataLabels: {
          enabled: false
        },
        showInLegend: true,
        borderWidth: 2,
        startAngle: 0,
        innerSize: '58%',
        allowPointSelect: false,
        dataLabels: false,
        stickyTracking: false,
        states: {
          hover: {
            enabled: false
          }
        },
        point: {
          events: {
            mouseOver: function(event) {
              this.series.chart.setTitle({
                text: generateChartText(false, this),
                x: -470,
                y: 113
              });
              $('.highcharts-title', $('#container')).addClass(this.name.toLowerCase());
            },
            mouseOut: function(event) {

              var someSeriesAreHidden = this.series.data.some(function(dataItem) {

                  return dataItem.hasOwnProperty('visible') && !dataItem.visible;
                }),
                xVal = someSeriesAreHidden ? -470 : -468,
                yVal = someSeriesAreHidden ? 113 : 124;
              this.series.chart.setTitle({
                text: generateChartText(!someSeriesAreHidden, this.series.chart),
                x: xVal,
                y: yVal
              });

              var highchartsTitle = $('.highcharts-title', $('#container'));
              highchartsTitle.removeClass();
              highchartsTitle.addClass('highcharts-title');
            },
            legendItemClick: function() {

              var $legend = $(this.legendGroup.div);

              $legend.hasClass('disable') ? $legend.removeClass('disable') : $legend.addClass('disable');

              var someSeriesAreHidden = this.series.data.some(function(dataItem) {
                  return dataItem.hasOwnProperty('visible') && !dataItem.visible;
                }),
                xVal = someSeriesAreHidden ? -470 : -468,
                yVal = someSeriesAreHidden ? 113 : 124;

              this.series.chart.setTitle({
                text: generateChartText(!someSeriesAreHidden, this.series.chart),
                x: xVal,
                y: yVal
              });
            }
          }
        }
      }
    },
    series: [{
      name: 'Brands',
      colorByPoint: true,
      data: [{
        name: 'Chrome',
        y: 24.03,
        searches: 1000
      }, {
        name: 'Firefox',
        y: 10.38,
        searches: 3000
      }]
    }]
  });
});

function generateChartText(isTotal, chart) {
  var series = chart.series[0],
    totalSearches = isTotal ? series.data[0].searches + series.data[1].searches : chart.searches / chart.y * 100;
  chart = Array.isArray(chart.series) ? (series.data[0].visible ? series.data[0] : series.data[1]) : chart;
  var textForSerie = '<span style="font-size: 13px;font-weight:normal;">' + chart.name + '</span><br>' + '<span style="fill: #797979;">' + parseInt(chart.searches, 10) + '</span><br><span>' + chart.y + '%</span><br>';
  var textForTotal = '<span style="font-size: 13px;font-weight:normal;">Total Searches' + '</span>' + '<br>' + '<span style="fill: #797979;">' + parseInt(totalSearches, 10) + '</span>';

  return isTotal ? textForTotal : textForSerie;
}

2 个答案:

答案 0 :(得分:0)

这是一个可能的策略:

  • Highcharts.chart()对象保存在全局变量
  • legendItemClick()处理程序中,使用点击的目标选择从全局chart变量中 点击的数据系列
  • 将未点击的数据系列传递给generateChartText()函数。

这里对您的代码稍作修改即可 - 修改附近有评论:

&#13;
&#13;
var chart;
$(document).ready(function() {

  // save the base chart object in a variable so any data series can be accessed on a click event
  chart = Highcharts.chart('container', {
    chart: {
      plotBackgroundColor: null,
      plotBorderWidth: null,
      plotShadow: false,
      type: 'pie',
      borderRadius: 0,
      width: 1200,
      height: 250,
      backgroundColor: '#fff',
      marginTop: 0,
      marginRight: 950,
      spacingTop: 0,
      spacingBottom: 0,
      spacingLeft: 0,
      events: {
        load: function(event) {

          this.setTitle({
            text: generateChartText(true, this),
            x: -468,
            y: 124
          });
        }
      }
    },
    legend: {
      useHTML: true,
      layout: 'vertical',
      verticalAlign: 'top',
      x: 0,
      y: 40,
      itemMarginBottom: 30,
      labelFormatter: function() {
        var description = this.name === 'Direct' ? 'Customers who use Chrome' : 'Customers who use Firefox';

        return '<div class="img"></div><div><span>' + this.name + '</span><br>' + '<p style="font-size: 13px; color: #666666;">' + description + '</p>' + '</div>';
      }
    },
    title: {
      text: 'Browser market shares January, 2015 to May, 2015'
    },
    tooltip: {
      pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
    },
    plotOptions: {
      pie: {
        allowPointSelect: true,
        cursor: 'pointer',
        dataLabels: {
          enabled: false
        },
        showInLegend: true,
        borderWidth: 2,
        startAngle: 0,
        innerSize: '58%',
        allowPointSelect: false,
        dataLabels: false,
        stickyTracking: false,
        states: {
          hover: {
            enabled: false
          }
        },
        point: {
          events: {
            mouseOver: function(event) {
              console.log(this)
              this.series.chart.setTitle({
                text: generateChartText(false, this),
                x: -470,
                y: 113
              });
              $('.highcharts-title', $('#container')).addClass(this.name.toLowerCase());
            },
            mouseOut: function(event) {

              var someSeriesAreHidden = this.series.data.some(function(dataItem) {

                  return dataItem.hasOwnProperty('visible') && !dataItem.visible;
                }),
                xVal = someSeriesAreHidden ? -470 : -468,
                yVal = someSeriesAreHidden ? 113 : 124;
              this.series.chart.setTitle({
                text: generateChartText(!someSeriesAreHidden, this.series.chart),
                x: xVal,
                y: yVal
              });

              var highchartsTitle = $('.highcharts-title', $('#container'));
              highchartsTitle.removeClass();
              highchartsTitle.addClass('highcharts-title');
            },
            legendItemClick: function(event) {
              var $legend = $(this.legendGroup.div);

              $legend.hasClass('disable') ? $legend.removeClass('disable') : $legend.addClass('disable');

              var someSeriesAreHidden = this.series.data.some(function(dataItem) {
                  return dataItem.hasOwnProperty('visible') && !dataItem.visible;
                }),
                xVal = someSeriesAreHidden ? -470 : -468,
                yVal = someSeriesAreHidden ? 113 : 124;

              // pass the series that was *not* clicked to generateChartText()
              this.series.chart.setTitle({
                text: generateChartText(false, event.target.name == "Chrome" ? chart.series[0].data[1] : chart.series[0].data[0]),
                x: -470,
                y: 113
              });
              // update the chart text
              $('.highcharts-title', $('#container')).addClass(this.name.toLowerCase());
            }
          }
        }
      }
    },
    series: [{
      name: 'Brands',
      colorByPoint: true,
      data: [{
        name: 'Chrome',
        y: 24.03,
        searches: 1000
      }, {
        name: 'Firefox',
        y: 10.38,
        searches: 3000
      }]
    }]
  });
});

function generateChartText(isTotal, chart) {
  var series = chart.series[0],
    totalSearches = isTotal ? series.data[0].searches + series.data[1].searches : chart.searches / chart.y * 100;
  chart = Array.isArray(chart.series) ? (series.data[0].visible ? series.data[0] : series.data[1]) : chart;
  var textForSerie = '<span style="font-size: 13px;font-weight:normal;">' + chart.name + '</span><br>' + '<span style="fill: #797979;">' + parseInt(chart.searches, 10) + '</span><br><span>' + chart.y + '%</span><br>';
  var textForTotal = '<span style="font-size: 13px;font-weight:normal;">Total Searches' + '</span>' + '<br>' + '<span style="fill: #797979;">' + parseInt(totalSearches, 10) + '</span>';

  return isTotal ? textForTotal : textForSerie;
}
&#13;
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>

<div id="container" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

以下是我的工作示例:JsFiddle

感谢@rphv给了我一些新的想法。

主要问题是legendItemClick点击系列的状态未在此事件中更改。

所以我可以收到点击的系列,它是之前的状态(可见真或假),并取决于预测的下一个系列状态。

function filterHiddenSeries(event) {
  return function(dataItem, index) {
    return (dataItem.hasOwnProperty('visible') && !dataItem.visible && event.target.index !== index) || (event.target.index === index && event.target.visible);
  }
}

这是在legendItemClick

上返回隐藏系列的功能