From: Jukka Kurkela Date: Mon, 28 Dec 2020 14:53:30 +0000 (+0200) Subject: Line: Use Path2D as cache (#8239) X-Git-Tag: v3.0.0-beta.8~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e530a4d1a0bd264885a559b1bb5213e26d898454;p=thirdparty%2FChart.js.git Line: Use Path2D as cache (#8239) * Line: Use Path2D as cache * Add comment, move to helpers, first and last point --- diff --git a/src/elements/element.line.js b/src/elements/element.line.js index 5ffca4393..039269786 100644 --- a/src/elements/element.line.js +++ b/src/elements/element.line.js @@ -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; + } } } diff --git a/src/helpers/helpers.extras.js b/src/helpers/helpers.extras.js index d62a7e19d..5bc7748c9 100644 --- a/src/helpers/helpers.extras.js +++ b/src/helpers/helpers.extras.js @@ -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)); +}