在 Highcharts 中通过循环添加系列的性能问题

问题描述

我必须用 Highcharts 创建一个散点图,从 api 中获取数据。 该 api 是使用 Django Rest Framework 用 Python 编写的,并从 Pandas Dataframe 开始返回数据,该数据将转换为列表并作为 JSON 传递。

我有一个名为 data 的主数据框,它有 3 列,结构如下:

| speed                | acc                 | id    |
| 0.09588048242649731  | 0.16578595340251923 | 185.0 |
| 1.8956370379738738   | 1.2269583940505981  | 192.0 |
| 0.12784064323532973  | 0.2449648529291153  | 185.0 |
...

我将此数据帧分成 N 个小数据帧,按列 id 对行进行分组,然后在列表中返回 N 个小数据帧。所以python中的api视图是这样的:

    @action(detail=True,methods=['get'])
    def chart_points(self,request,pk):
        instance = MyObject.objects.get(pk=pk)
        data = instance.data
        data_list = {
            "data_list": [v.values.tolist() for k,v in data.groupby('id')]
        }
        return Response(data_list)

当我调用它时,它给了我这样的响应:

{ "data_list": [
            [
                [
                    0.09588048242649731,0.16578595340251923,185.0
                ],[
                    0.12784064323532973,0.2449648529291153,[
                    0.14382072363974596,0.14911147952079773,...
             ],[
                [
                    1.8956370379738738,0.18043938279151917,192.0
                ],[
                    1.8976345480244257,1.2269583940505981,[
                    1.8986333030497016,0.2929287254810333,...
}

我在应用程序的客户端使用 Backbonejs,我有一个模型可以调用一个端点并保存响应数据。

数据的检索相对较快(大约需要 10 秒,这与我手动调用 api 时等待的时间相同)。

在此期间,我在页面上创建空图表并等待 api 响应。 当我检索数据时,我会遍历它们并以这种方式将每个系列添加到图表中:

var data_list = this.model.get('data_list');
for( let i = 0; i < data_list.length; i++ ) {
    this.chart.addSeries({
        type: 'scatter',name: `Element number ${data_list[i][0][2]}`,data: data_list[i],});
}

其中 this.chart 是我要用所有 N 系列填充的 Highcharts 图表。

问题是这个最终过程非常缓慢(它需要越来越多的分钟,并且还会冻结页面)。

我注意到,如果我将 same 系列 N 次添加到图表中(也是最大长度的系列),它花费的时间要少得多。比如这样:

var data_list = this.model.get('data_list');
for( let i = 0; i < data_list.length; i++ ) {
    this.chart.addSeries({
        type: 'scatter',name: `Element number ${data_list[0][0][2]}`,data: data_list[0],});
}

我可以做些什么来提高性能

解决方法

每次迭代后都会重新绘制图表,您可以通过将 redraw 方法调用中的 addSeries 参数设置为 false 并在循环后调用 redraw 来防止这种情况发生。

for( let i = 0; i < data_list.length; i++ ) {
  this.chart.addSeries({
    name: ...,data: ...,},false);
}

chart.redraw();

现场演示: http://jsfiddle.net/yqo8hrbn/

API 参考:

https://api.highcharts.com/class-reference/Highcharts.Chart#addSeries

https://api.highcharts.com/class-reference/Highcharts.Chart#redraw