Chart.js 性能
Chart.js 图表在画布元素上呈现,这使得呈现速度非常快。 对于大型数据集或性能敏感的应用程序,我们可能希望考虑以下提示。
数据结构和格式
Parsing
以数据集和尺度接受的内部格式提供准备好的数据,并设置 parsing: false
。 有关详细信息,请参阅数据结构 。
数据标准化
如果我们为数据提供具有唯一、排序和跨数据集一致的索引的数据,并提供 normalized: true
选项让 Chart.js 知道我们已经这样做了,那么 Chart.js 是最快的。 即使没有此选项,有时仍可以更快地提供已排序的数据。
抽取(Decimation)
抽取数据将获得最佳结果。 当要在图表上显示大量数据时,在只有几百像素宽的图表上显示数以万计的数据点是没有意义的。
抽取插件可与折线图一起使用,以在呈现图表之前抽取数据。 这将提供最佳性能,因为它将减少渲染图表所需的内存。
当满足某些条件时,折线图能够在绘制期间进行自动数据抽取。 由于自动抽取发生在图表生命周期的后期,我们仍应考虑在传递数据之前自行抽取数据以获得最佳性能。
刻度计算
旋转
通过将 minRotation
和 maxRotation
设置为相同的值来指定旋转值,这样可以避免图表必须自动确定要使用的值。
采样
设置 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 // 默认在所有数据集中禁用
}
}
}
});