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
/**
* 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
/**
* 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
this.options = undefined;
this._loop = undefined;
this._fullLoop = undefined;
+ this._path = undefined;
this._points = undefined;
this._segments = undefined;
this._pointsUpdated = false;
set points(points) {
this._points = points;
delete this._segments;
+ delete this._path;
}
get points() {
/**
* 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)
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;
+ }
}
}
+
export function fontString(pixelSize, fontStyle, fontFamily) {
return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
}
* @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));
+}