HighCharts在建立多个图表时加载数据很慢。

3
我有一个页面上有两个HighCharts图表,想知道是否有方法可以加速图表的加载时间。第一个是主要图表,有两个系列;第二个是“缩略图”图表,有四个系列。
我会在列表框中填充一些日期,并且当用户选择每个日期时,我会发起一个ajax调用来获取一些数据。
我使用类似于构造函数的方式来构建我的图表,如下所示...
basicMaxChart = function() {        
    options = {
    chart: {},
    /*missed for brevity*/,
    series: [{},{}] 
    }; // options
    return options;
}; // Max

basicMiniChart = function() {       
    optionsMini = {
    chart: {},
    /*missed for brevity*/,
    series: [{},{},{},{}] 
    }; // optionsMini
    return optionsMini;
}; // Mini

我的文档准备完毕函数,

// Globals
var options;
var optionsMini;

var chart;
var chartMini;

jQuery("document").ready(function() {

    function createChart() {
        options = $.extend({}, basicMaxChart options);
        chart = new Highcharts.Chart(options);  
    };

    function createMiniChart() {
        optionsMini = $.extend({}, basicMiniChart(), optionsMini);
        chartMini = new Highcharts.Chart(optionsMini);
    };

    // create some empty charts for place holders
    createChart();
    createMiniChart();

    function loadData(){
        // missed for brevity, but declare some vars and get some values from inputs
        var aLen = document.getElementById("someInput").value;
        var d1 ...

        var data = {
                compareD1   : d1,
                m1          : m1,
                someVal     : aLen
               };
            $.post("getSomeData.php", data, function(json) {
                /* Clearing the series first or ‘Destroying’ the chart only only serves to make things worse …
                if (typeof chartMini != 'undefined') {
                    while(chartMini.series.length > 0)
                    chartMini.series[0].remove();
                    //chartMini.destroy();
                }
                */
                options.series[0] = json[0]; 
                options.series[1] = json[1];

                optionsMini.series[0] = json[3];
                optionsMini.series[1] = json[4];
                optionsMini.series[2] = json[5];
                optionsMini.series[3] = json[6];

                chart = new Highcharts.Chart(options);              
                chartMini = new Highcharts.Chart(optionsMini);

                chart.series[0].options.color = 'blue';
                chart.series[0].update(chart.series[0].options);
                chart.series[1].options.color = 'red';
                chart.series[1].update(chart.series[1].options);

                chartMini.series[0].options.color = '#A9CBE9';
                ….
                ….
                chartMini.series[3].update(chartMini.series[3].options);

            }, "json");
}); // ready
loadData函数发出一个ajax调用并返回一个包含两个图表数据的json对象,大约需要500ms的时间。(我对getSomeData.php脚本的速度感到满意)。
如果我从loadData函数中删除与chartMini / optionsMini有关的所有内容,主要的图表也加载得非常快。但是一旦我把'Mini'加回去,事情就变慢了,两个图表都需要大约5秒钟才能显示出来(实际上,我经常在FireFox中收到“未响应”的消息)。我的json对象中每个“数据”元素都有700个数据点(我认为这并不特别大)。
我想我的高级图表经验导致了速度慢。请问您有任何建议,我如何提高这两个图表的构建/加载时间性能。
感谢您的阅读。

我不确定你为什么要创建图表,然后继续更新选项?你应该先完成所有选项,然后再创建图表。我指的是像 chart.series[0].update(chart.series[0].options); 这样的代码行。 - Halvor Holsten Strand
@ Ondkloss。这是一个非常好的观点,谢谢。我会解决这个问题的。我认为这主要是由于我对JavaScript / Highcharts等方面缺乏经验。我想我应该将它放在图表的构造函数中。 - Johnny
1个回答

3

从您展示的代码中可以看出,在创建图表后,持续更新它是成本较高的。每次调用update方法都会强制进行redraw,这非常耗费资源。

理想情况下,在创建图表之前完成所有选项。这在一定程度上取决于您的JSON是否正确,但可以想象以下代码:

options.series[0] = json[0];
options.series[0].options.color = 'blue';   
options.series[1] = json[1];
options.series[1].options.color = 'red';

optionsMini.series[0] = json[3];
optionsMini.series[0].options.color = '#A9CBE9';
// ...

chart = new Highcharts.Chart(options);              
chartMini = new Highcharts.Chart(optionsMini);

如果在您的JSON中还没有options对象,则可能需要创建它。

另一种懒惰的替代方法是延迟当前代码中的redraw,然后手动执行一次redraw。想象一下:

chart = new Highcharts.Chart(options);              
chartMini = new Highcharts.Chart(optionsMini);

chart.series[0].options.color = 'blue';
chart.series[0].update(chart.series[0].options, false); // false to prevent redraw
chart.series[1].options.color = 'red';
chart.series[1].update(chart.series[1].options, false); // false to prevent redraw

chartMini.series[0].options.color = '#A9CBE9';
chartMini.series[0].update(chartMini.series[0].options, false); // false to prevent redraw
// ...

chart.redraw(); // force redraw after all changes are made
chartMini.redraw(); // force redraw after all changes are made

请注意,这种方法比第一种方法慢,因为它需要多次更新系列中的大量数据,并且对每个图表进行一次redraw,而第一种方法不会发生这种情况。

1
再次感谢您...您的话非常有道理。我之前没有意识到每次“更新”调用都会涉及重新绘制。我想我现在恍然大悟了。 - Johnny
尝试一下,看看它是否解决了你的问题。如果有任何问题,请告诉我。 - Halvor Holsten Strand
谢谢。我已经接受了你的答案,因为我可以看到图表速度有明显的改善,并且学到了宝贵的东西。我认为它可能会加载得更快,但我应该查看SO而不是“扩展”这个问题。我仍然在FF的标题栏中收到一些“未响应”的消息,但没有像以前那么多。我肯定欠你一杯啤酒。 - Johnny
顺便提一下,我采用了你的第一种方法。也许我应该指出,“options.series [0] .options.color ='blue';”实际上是“options.series [0] .color ='blue';”。 - Johnny
将更新参数设置为false,并在加载数据到选项中结束时重新绘制,这对我来说是关键。谢谢! - Christopher Mills

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接