Chart.js 性能

Chart.js 图表在画布元素上呈现,这使得呈现速度非常快。 对于大型数据集或性能敏感的应用程序,我们可能希望考虑以下提示。

数据结构和格式

Parsing

以数据集和尺度接受的内部格式提供准备好的数据,并设置 parsing: false。 有关详细信息,请参阅数据结构

数据标准化

如果我们为数据提供具有唯一、排序和跨数据集一致的索引的数据,并提供 normalized: true 选项让 Chart.js 知道我们已经这样做了,那么 Chart.js 是最快的。 即使没有此选项,有时仍可以更快地提供已排序的数据。

抽取(Decimation)

抽取数据将获得最佳结果。 当要在图表上显示大量数据时,在只有几百像素宽的图表上显示数以万计的数据点是没有意义的。

抽取插件可与折线图一起使用,以在呈现图表之前抽取数据。 这将提供最佳性能,因为它将减少渲染图表所需的内存。

当满足某些条件时,折线图能够在绘制期间进行自动数据抽取。 由于自动抽取发生在图表生命周期的后期,我们仍应考虑在传递数据之前自行抽取数据以获得最佳性能。


刻度计算

旋转

通过将 minRotationmaxRotation 设置为相同的值来指定旋转值,这样可以避免图表必须自动确定要使用的值。

采样

设置 ticks.sampleSize 选项。 这将通过仅查看标签的一个子集来确定标签的大小,以便更快地渲染轴。 如果标签大小没有太大差异,这种方法效果最好。


禁用动画

如果我们的图表有很长的渲染时间,最好禁用动画。 这样做意味着图表只需要在更新期间渲染一次,而不是多次。 这将具有降低 CPU 使用率和提高一般页面性能的效果。 当动画被禁用且 Path2D 可用时,折线图使用 Path2D 缓存。

new Chart(ctx, {
    type: 'line',
    data: data,
    options: {
        animation: false
    }
});

指定比例的最小值 min 和最大值 max

如果我们指定最小值和最大值,则比例不必根据数据计算范围。

new Chart(ctx, {
    type: 'line',
    data: data,
    options: {
        scales: {
            x: {
                type: 'time',
                min: new Date('2019-01-01').valueOf(),
                max: new Date('2019-12-31').valueOf()
            },
            y: {
                type: 'linear',
                min: 0,
                max: 100
            }
        }
    }
});

使用 Web Worker 进行并行渲染(仅限 Chromium)

Chromium(Chrome:版本 69,Edge:79,Opera:56)添加了将画布的渲染控制转移到 Web Worker 的能力。 Web Worker 可以使用 OffscreenCanvas API 从 Web Worker 渲染到 DOM 中的画布上。 Chart.js 是一个基于画布的库,支持在 Web Worker 中渲染 - 只需将 OffscreenCanvas 传递给 Chart 构造函数,而不是 Canvas 元素。 请注意,截至今天,此 API 仅在基于 Chromium 的浏览器中受支持。

通过将所有 Chart.js 计算转移到一个单独的线程中,可以释放主线程用于其他用途。 在 Web Worker 中使用 Chart.js 时的一些提示和技巧:

  • 在线程之间传输数据可能会很昂贵,因此请确保您的配置和数据对象尽可能小。 如果可以,请尝试在工作人员端生成它们(工作人员可以发出 HTTP 请求!)或将它们作为 ArrayBuffers 传递给工作人员,它可以从一个线程快速传输到另一个线程。
  • 我们不能在线程之间传输函数,因此如果配置对象包含函数,则必须在传输之前将它们剥离,然后再将它们添加回来。
  • 我们无法从工作线程访问 DOM,因此使用 DOM(包括任何鼠标交互)的 Chart.js 插件可能无法正常工作。
  • 如果支持除最现代的 Chromium 浏览器之外的浏览器,请确保有备用方案。
  • 必须手动调整图表大小。 请参阅下面的示例。
const config = {};
const canvas = new HTMLCanvasElement();
const offscreenCanvas = canvas.transferControlToOffscreen();

const worker = new Worker('worker.js');
worker.postMessage({canvas: offscreenCanvas, config}, [offscreenCanvas]);

worker.js 中的示例代码:

onmessage = function(event) {
    const {canvas, config} = event.data;
    const chart = new Chart(canvas, config);

    // 必须手动调整图表大小,因为 OffscreenCanvas 不包括事件侦听器。
    canvas.width = 100;
    canvas.height = 100;
    chart.resize();
};

折线图

禁用贝塞尔曲线

如果在图表上绘制线条,禁用 Bézier 曲线将缩短渲染时间,因为绘制直线比 Bézier 曲线更高效。 默认情况下禁用贝塞尔曲线。

绘图期间自动抽取数据

线元素将自动抽取数据,当张力、阶梯和边界线设置为其默认值(分别为 false、0 和 [])时。 这通过跳过不可见线段的绘制来提高渲染速度。

启用spanGaps

如果有很多数据点,则启用 spanGaps 可能会提高性能。 这会禁用线的分段,这可能是一个不需要的步骤。

启用 spanGaps

new Chart(ctx, {
    type: 'line',
    data: {
        datasets: [{
            spanGaps: true // 启用单个数据集
        }]
    },
    options: {
        spanGaps: true // 启用所有数据集
    }
});

禁用线条绘制

如果有很多数据点,则禁用数据集的线渲染并仅绘制点可能会更高效。 这样做意味着在画布上绘制的内容更少,这将提高渲染性能。

new Chart(ctx, {
    type: 'line',
    data: {
        datasets: [{
            showLine: false // disable for a single dataset
        }]
    },
    options: {
        showLine: false // disable for all datasets
    }
});

禁用点绘图

如果有很多数据点,禁用数据集的点渲染并仅绘制线可能会更高效。 这样做意味着在画布上绘制的内容更少,这将提高渲染性能。

new Chart(ctx, {
    type: 'line',
    data: {
        datasets: [{
            pointRadius: 0 // 禁用单个数据集
        }]
    },
    options: {
        datasets: {
            line: {
                pointRadius: 0 // 禁用所有“线”数据集
            }
        },
        elements: {
            point: {
                radius: 0 // 默认在所有数据集中禁用
            }
        }
    }
});

查看笔记

扫码一下
查看教程更方便