Highcharts自动计算多个系列位置

时间:2016-09-01 08:43:12

标签: javascript highcharts

我实际上有一个包含多个数据系列的饼图,每个数据都以饼图表示(参见JSFiddle链接)。

我正在寻找一种方法来实现每个饼图的最佳大小的“自动”计算和最佳位置,以便以通用方式将它们全部呈现在一个单个容器中。

我已经开始提出解决方案,但它确实不是最佳选择。

要么我不了解Highcharts在生成图表时如何工作,要么我的系统能够进行计算或者两者都有未知的价值。

请注意,如果使用更多系列,生成器仅适用于1到6个不同系列的数据,因为我没有进行计算,因此无法获得放置。

此外,它确实只适用于这些尺寸的容器:

  • 宽度:340px高度:170px
  • 宽度:680px高度:170px

在宽度或高度较高的容器上,系统将无法计算位置。

这实际上是我寻找如何获得最佳和通用位置计算器的想法的一部分。

这是我附带的代码和代码示例后的JSFiddle链接。

// Pie Chart Class
var pieChart = {
    create: function(_title, _data, _color, _height, _width) {
        return (function() {

            var type = 'pie';
            var title = _title || "defaultName";
            var color = _color || "#EBEBEB";
            var height = _height || 170;
            var width = _width || 340;
            var series = [];
            var chart;
            var sizeData = getSize(height, width);
            if (_data)
                newSeries(_data);

            // Public functions
            function newSeries(_data) {
                var _datas = [];

                for (var dataSet in _data) {
                    if (_data.hasOwnProperty(dataSet) && (color != null && color != undefined)) {
                        _datas.push({
                            name: dataSet,
                            y: _data[dataSet],
                        });
                    }
                }

                series.push({
                    data: _datas,
                    borderWidth: 0,
                    center: []
                });
                setPos(series.length);
            }

            function Series() {
                return (JSON.stringify(series));
            }

            function drawOn(item) {
                if (!item || !document.getElementById(item) && !chart)
                    return (null);
                else {
                    chart = new Highcharts.Chart({
                        chart: {
                            renderTo: item,
                            backgroundColor: color,
                            plotBackgroundColor: null,
                            plotBorderWidth: null,
                            plotShadow: false,
                            type: 'pie'
                        },
                        title: {
                            text: title
                        },
                        plotOptions: {
                            pie: {
                                allowPointSelect: false,
                                borderWidth: 0,
                                dataLabels: {
                                    distance: -1,
                                    enabled: true,
                                    format: '<b>{point.name}</b>: {point.y}',
                                    style: {
                                        color: 'black'
                                    }
                                },
                                size: sizeData.size
                            }
                        },
                        series: JSON.parse(Series())
                    });
                }
            }

            // Private functions
            function setPos(_len) {
                if (_len == 1)
                    series[0].center = [sizeData.center, sizeData.h];
                else if (_len == 2) {
                    series[0].center = [sizeData.second, sizeData.h];
                    series[1].center = [sizeData.fourth, sizeData.h];
                } else if (_len == 3) {
                    series[0].center = [sizeData.w1, sizeData.h];
                    series[1].center = [sizeData.center, sizeData.h];
                    series[2].center = [sizeData.w6, sizeData.h];
                } else if (_len == 4) {
                    series[0].center = [(sizeData.w1 + sizeData.w2) / 2, sizeData.h];
                    series[1].center = [sizeData.w3, sizeData.h];
                    series[2].center = [(sizeData.w4 + sizeData.w5) / 2, sizeData.h];
                    series[3].center = [sizeData.w6, sizeData.h];
                } else if (_len == 5) {
                    series[0].center = [sizeData.w1, sizeData.h];
                    series[1].center = [sizeData.second, sizeData.h];
                    series[2].center = [sizeData.center, sizeData.h];
                    series[3].center = [sizeData.fourth, sizeData.h];
                    series[4].center = [sizeData.w6, sizeData.h];
                } else if (_len == 6) {
                    series[0].center = [sizeData.w1, sizeData.h];
                    series[1].center = [sizeData.w2, sizeData.h];
                    series[2].center = [sizeData.w3, sizeData.h];
                    series[3].center = [sizeData.w4, sizeData.h];
                    series[4].center = [sizeData.w5, sizeData.h];
                    series[5].center = [sizeData.w6, sizeData.h];
                }
            }

            function getSize(height, width) {
                var nbChart = 6;
                var diam;
                var tmpWidth = width - 30;
                if (nbChart == 1)
                    diam = height - ( height / 3);
                else {
                    diam = (tmpWidth - (tmpWidth / nbChart)) / nbChart;
                }
                var test = (tmpWidth - (diam * nbChart));
                var h = ((height - diam) / 2) / 2;
                var w = diam + (test / (nbChart * 2));
                var decal;
                if (width >= 680)
                    decal = test / 10;
                else
                    decal = 0;
                return {
                    width: width,
                    height: height,
                    size: diam,
                    h: h,
                    w1: ((diam / 2) + decal),
                    w2: (((w) + diam / 2) + decal),
                    w3: (((w * 2) + diam / 2) + decal),
                    w4: (((w * 3) + diam / 2) + decal),
                    w5: (((w * 4) + diam / 2) + decal),
                    w6: (((w * 5) + diam / 2) + decal),
                    center: (((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2),
                    second: (((diam / 2) + decal) + (((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2)) / 2,
                    fourth: ((((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2) + (((w * 5) + diam / 2) + decal)) / 2
                }
            }

            return {
                Series: Series,
                drawOn: drawOn,
                newSeries: newSeries
            }
        })();
    }
};

var crPie = pieChart.create('Test', {T1: 500, T2: 700}, "#EBEBEB", 170, 680);
crPie.newSeries({T1: 700, T2: 800});
crPie.drawOn('container');

(这是JSFiddle链接:https://jsfiddle.net/jcL0wuwp/

我通过互联网进行多项研究,但没有找到我想要的东西,这是获得数据系列最佳位置和大小的方法。

(我知道代码的某些部分不是最优的,但我的问题不是关于如何优化或使用JS中的类,尽管我不是很好的建议。)

1 个答案:

答案 0 :(得分:2)

我会改变你对馅饼系列定位的想法。我更喜欢包装Higcharts的getCenter方法,因此可以使用响应式图表:

(function(H) {
    H.wrap(H.Chart.prototype, 'addSeries', function(proceed, options, redraw, animation) {
      proceed.apply(this, Array.prototype.slice.call(arguments, 1));
      var chart = this;
      Highcharts.each(chart.series, function(s) {
        s.isDirty = true;
      });
      chart.redraw();
    });

    H.wrap(H.seriesTypes.pie.prototype, 'getCenter', function(proceed) {
      var series = this,
        chart = series.chart,
        width = chart.chartWidth,
        height = chart.chartHeight,
        numberOfSeries = chart.series.length,
        index = series._i,
        initialSize, size, centerY = height / 2,
        centerX;
      centerX = (index + 1) * (width / (numberOfSeries + 1));
      initialSize = width / (numberOfSeries + 1);
      size = initialSize > height ? height : initialSize;
      return [centerX, centerY, size, 0]
    });
  }(Highcharts));

我使用了多个系列来计算你的馅饼系列的新尺寸和中心位置。我已经更改了addSeries方法,因此您也可以添加自定义饼图系列。

在这里您可以找到一个如何工作的示例: http://jsfiddle.net/oohn3q22/6/