Highcharts Donutchart: Avoid showing duplicate leg

2019-09-07 19:21发布

问题:

I am trying to represent nested data using Highcharts Donut Chart. The charts are generated quite well, however I am having some problems with displaying the legend.

Data to be represented: Category A -[High : 20%, | Medium : 50% | Low : 30%] Category B -[High : 10% | Medium : 50% | Low : 40%]

JS Fiddle : http://jsfiddle.net/a2sy9bgj/

  $(function () {
    // Build the data arrays
    var categoryData = [{
        name: 'Category A',
        y : 60,
        color: 'white',
        borderColor : 'black'
       },
       {
        name: 'Category B',
        y : 40,
        color: 'white',
        borderColor : 'black'
       }];

    var priorityData = [
      {
        name: 'High',
        y : 10,
        category : 'Category A',
        color: 'Red',
      }, 
      {
        name: 'Medium',
        y : 30,
        category : 'Category A',
        color: 'Yellow',
      }, {
        name: 'Low',
        y : 20,
        category : 'Category A',
        color: 'Green',
      },{
        name: 'High',
        y : 20,
        category : 'Category B',
        color: 'Red'
      }, 
      {
        name: 'Medium',
        y : 10,
        category : 'Category B',
        color: 'Yellow',
      }, {
        name: 'Low',
        y : 10,
        category : 'Category B',
        color: 'Green',
      }
    ];

        // Create the chart
        $('#container').highcharts({
            chart: {
                type: 'pie'
            },
            title: {
                text: 'Browser market share, April, 2011'
            },
            yAxis: {
                title: {
                    text: 'Total percent market share'
                }
            },
            plotOptions: {
                pie: {
                    showInLegend : true,
                    shadow: false,
                    center: ['50%', '50%'],
                }
            },
            tooltip: {
                valueSuffix: '%'
            },
            series: [{
                name: 'Category',
                showInLegend : false,
                data: categoryData,
                size: '60%'               
            }, {
                name: 'Priority',
                data: priorityData,
                size: '80%',
                innerSize: '60%'
             }]
        });
    });

I've created two series 1. Category Data 2. Priority Data

The legend should show High, Medium and Low, but since the priority data has this information(High, Medium and Low) twice, the Legend shows High, Medium and Low twice.

Is there any way to show the legend only once when the data in the series may have duplicates?

回答1:

In the Highcharts you can only hide/show one series. In the pie chart, even you have legend item per slice, there still is just one series.

However, there is hope for you: you can overwrite method responsible for that:

(function (H) {
    var UNDEFINED;
    /**
     * Returns true if the object is not null or undefined. Like MooTools' $.defined.
     * @param {Object} obj
     */
    function defined(obj) {
        return obj !== UNDEFINED && obj !== null;
    }
    H.wrap(H.Legend.prototype, 'getAllItems', function (p) {
        var allItems = [],
            pointsForLegend = [];
        H.each(this.chart.series, function (series) {
            var seriesOptions = series.options;

            // Handle showInLegend. If the series is linked to another series, defaults to false.
            if (!H.pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? UNDEFINED : false, true)) {
                return;
            }

            if (series.legendItems) {
                // use points or series for the legend item depending on legendType
                allItems = allItems.concat(series.legendItems);
            } else if (seriesOptions.legendType === 'point') {
                H.each(series.data, function (e, i) {
                    if (e.showInLegend) {
                        pointsForLegend.push(e);
                    }
                })
                allItems = allItems.concat(pointsForLegend);
            } else {
                allItems = allItems.concat(series);
            }
        });
        return allItems;
    });
})(Highcharts);

Now, just set per point, if should be displayed or not:

 point.showInLegend: i // 0 == false, 1 == true

Demo for you: http://jsfiddle.net/a2sy9bgj/6/

Of course, there one thing remains: click on one legend probably should hide two slices. In such case, use legendItemClick and find corresponding points to hide them.