]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Line: Use Path2D as cache (#8239)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Mon, 28 Dec 2020 14:53:30 +0000 (16:53 +0200)
committerGitHub <noreply@github.com>
Mon, 28 Dec 2020 14:53:30 +0000 (09:53 -0500)
* Line: Use Path2D as cache
* Add comment, move to helpers, first and last point

src/elements/element.line.js
src/helpers/helpers.extras.js

index 5ffca43938fe4b8cf49d5b03d74ca73b08abc19d..039269786a4eeb4c61f6f53610e1e09f51a84b0c 100644 (file)
@@ -3,6 +3,7 @@ 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
@@ -50,7 +51,7 @@ function pathVars(points, segment, params) {
 /**
  * Create path from points, grouping by truncated x-coordinate
  * Points need to be in order by x-coordinate for this to work efficiently
- * @param {CanvasRenderingContext2D} ctx - Context
+ * @param {CanvasRenderingContext2D|Path2D} ctx - Context
  * @param {LineElement} line
  * @param {object} segment
  * @param {number} segment.start - start index of the segment, referring the points array
@@ -97,7 +98,7 @@ function pathSegment(ctx, line, segment, params) {
 /**
  * Create path from points, grouping by truncated x-coordinate
  * Points need to be in order by x-coordinate for this to work efficiently
- * @param {CanvasRenderingContext2D} ctx - Context
+ * @param {CanvasRenderingContext2D|Path2D} ctx - Context
  * @param {LineElement} line
  * @param {object} segment
  * @param {number} segment.start - start index of the segment, referring the points array
@@ -206,6 +207,7 @@ export default class LineElement extends Element {
                this.options = undefined;
                this._loop = undefined;
                this._fullLoop = undefined;
+               this._path = undefined;
                this._points = undefined;
                this._segments = undefined;
                this._pointsUpdated = false;
@@ -228,6 +230,7 @@ export default class LineElement extends Element {
        set points(points) {
                this._points = points;
                delete this._segments;
+               delete this._path;
        }
 
        get points() {
@@ -317,7 +320,7 @@ export default class LineElement extends Element {
 
        /**
         * Append all segments of this line to current path.
-        * @param {CanvasRenderingContext2D} ctx
+        * @param {CanvasRenderingContext2D|Path2D} ctx
         * @param {number} [start]
         * @param {number} [count]
         * @returns {undefined|boolean} - true if line is a full loop (path should be closed)
@@ -357,16 +360,25 @@ export default class LineElement extends Element {
 
                setStyle(ctx, options);
 
-               ctx.beginPath();
-
-               if (this.path(ctx, start, count)) {
-                       ctx.closePath();
+               let path = this._path;
+               if (!path) {
+                       path = this._path = new Path2D();
+                       if (this.path(path, start, count)) {
+                               path.closePath();
+                       }
                }
 
-               ctx.stroke();
+               ctx.stroke(path);
+
                ctx.restore();
 
-               this._pointsUpdated = false;
+               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;
+               }
        }
 }
 
index d62a7e19d66611cf7debc82931b9338a3938dab8..5bc7748c9d7bbf6b082e8f83e629621a150a5c79 100644 (file)
@@ -1,3 +1,4 @@
+
 export function fontString(pixelSize, fontStyle, fontFamily) {
        return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
 }
@@ -55,3 +56,14 @@ 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));
+}