Disable Path2D caching when chart is animated (#8319)

* Disable Path2D caching when chart is animated
* Add note to performance docs
This commit is contained in:
Jukka Kurkela 2021-01-16 21:06:27 +02:00 committed by GitHub
parent a58d43cbda
commit ea34e8b814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 24 deletions

View File

@ -35,6 +35,7 @@ Set the [`ticks.sampleSize`](./axes/cartesian/index.mdx#tick-configuration) opti
## Disable Animations
If your charts have long render times, it is a good idea to disable animations. Doing so will mean that the chart needs to only be rendered once during an update instead of multiple times. This will have the effect of reducing CPU usage and improving general page performance.
Line charts use Path2D caching when animations are disabled.
To disable animations

View File

@ -29,9 +29,13 @@ export default class LineController extends DatasetController {
// Update Line
line.points = points;
// In resize mode only point locations change, so no need to set the options.
if (mode !== 'resize') {
me.updateElement(line, undefined, {options: me.resolveDatasetElementOptions()}, mode);
me.updateElement(line, undefined, {
animated: !animationsDisabled,
options: me.resolveDatasetElementOptions()
}, mode);
}
// Update Points

View File

@ -3,7 +3,6 @@ import {_bezierInterpolation, _pointInLine, _steppedInterpolation} from '../help
import {_computeSegments, _boundSegments} from '../helpers/helpers.segment';
import {_steppedLineTo, _bezierCurveTo} from '../helpers/helpers.canvas';
import {_updateBezierControlPoints} from '../helpers/helpers.curve';
import {_coordsAnimated} from '../helpers/helpers.extras';
/**
* @typedef { import("./element.point").default } PointElement
@ -204,6 +203,7 @@ export default class LineElement extends Element {
constructor(cfg) {
super();
this.animated = true;
this.options = undefined;
this._loop = undefined;
this._fullLoop = undefined;
@ -351,8 +351,9 @@ export default class LineElement extends Element {
* @param {number} [count]
*/
draw(ctx, chartArea, start, count) {
const options = this.options || {};
const points = this.points || [];
const me = this;
const options = me.options || {};
const points = me.points || [];
if (!points.length || !options.borderWidth) {
return;
@ -362,10 +363,10 @@ export default class LineElement extends Element {
setStyle(ctx, options);
let path = this._path;
let path = me._path;
if (!path) {
path = this._path = new Path2D();
if (this.path(path, start, count)) {
path = me._path = new Path2D();
if (me.path(path, start, count)) {
path.closePath();
}
}
@ -374,12 +375,10 @@ export default class LineElement extends Element {
ctx.restore();
if (_coordsAnimated(points[0]) || _coordsAnimated(points[points.length - 1])) {
// When point coordinates are animating, we need to recalculate the
// path (and control points when beziers are used). Only coordinates
// matter, other animations are ignored.
this._pointsUpdated = false;
this._path = undefined;
if (me.animated) {
// When line is animated, the control points and path are not cached.
me._pointsUpdated = false;
me._path = undefined;
}
}
}

View File

@ -56,14 +56,3 @@ export const _toLeftRightCenter = (align) => align === 'start' ? 'left' : align
* @private
*/
export const _alignStartEnd = (align, start, end) => align === 'start' ? start : align === 'end' ? end : (start + end) / 2;
/**
* Return true if `x` or `y` property (coordinates) of the element is currently animated.
* @param {object} element
* @returns {boolean}
* @private
*/
export function _coordsAnimated(element) {
const anims = element && element.$animations;
return anims && ((anims.x && anims.x.active()) || (anims.y && anims.y.active()));
}

View File

@ -10,4 +10,26 @@ describe('Chart.elements.LineElement', function() {
expect(line).not.toBe(undefined);
expect(line.points).toEqual([1, 2, 3, 4]);
});
it('should not cache path when animations are enabled', function(done) {
var chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
data: [0, -1, 0],
label: 'dataset1',
}],
labels: ['label1', 'label2', 'label3']
},
options: {
animation: {
duration: 50,
onComplete: () => {
expect(chart.getDatasetMeta(0).dataset._path).toBeUndefined();
done();
}
}
}
});
});
});