]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Disable Path2D caching when chart is animated (#8319)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Sat, 16 Jan 2021 19:06:27 +0000 (21:06 +0200)
committerGitHub <noreply@github.com>
Sat, 16 Jan 2021 19:06:27 +0000 (14:06 -0500)
* Disable Path2D caching when chart is animated
* Add note to performance docs

docs/docs/general/performance.md
src/controllers/controller.line.js
src/elements/element.line.js
src/helpers/helpers.extras.js
test/specs/element.line.tests.js

index 25dfaadc81267fb5d1eb6cc6b0de072825677b70..51cde5c05c29d0268d5f9bc4b5e16b86c5733ca6 100644 (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
 
index 16edd7cb368e3272668ec90faaeee9f20d879fba..3690fa90dbce24f7b1e39e1208ee0d5b927dc91f 100644 (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
index 5d0a276323f5b96d421c0b3459a8a4fc6fe2131c..9379bae53f724c1ceadee83fb7db8ed33bb4c736 100644 (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;
                }
        }
 }
index b140cdd7f69e1221ae6418a1cd467d995737c3f2..280ad832bc77b8b6b45cd506de11d940831d072d 100644 (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()));
-}
index 2299de2196ef436ed52fec8750b2f611f6668f18..e29d5c44f6af6415e482cb84701b551d06b92888 100644 (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();
+                                       }
+                               }
+                       }
+               });
+       });
 });