UNPKG

@visactor/vrender-animate

Version:

This module provides a graph-based animation system for VRender.

1,295 lines (1,278 loc) 655 kB
import { Color, isNumber, isArray, isFunction, pi2, pointAt, Point, isString, EventEmitter, tau, halfPi, AABBBounds, degreeToRadian, PointService, abs, max, min, atan2, epsilon, Matrix, Logger, isPointInLine, pi, isBoolean, isObject, sqrt, OBBBounds, isEqual, isNil, normalTransform, isValidUrl, isBase64, isValidNumber, mixin, clamp, isValid, isNumberClose } from '@visactor/vutils'; import { CustomPath2D as CustomPath2D$1, application as application$1, splitRect, splitArc, splitCircle, splitLine, splitPolygon, splitArea, splitPath, AttributeUpdateType as AttributeUpdateType$1, interpolateColor as interpolateColor$1, pathToBezierCurves, applyTransformOnBezierCurves, alignBezierCurves, findBestMorphingRotation, ColorStore as ColorStore$1, ColorType as ColorType$1, pointInterpolation as pointInterpolation$1, vglobal, RichText, divideCubic as divideCubic$1 } from '@visactor/vrender-core'; var ColorType; !function (ColorType) { ColorType[ColorType.Color255 = 0] = "Color255", ColorType[ColorType.Color1 = 1] = "Color1"; }(ColorType || (ColorType = {})); class ColorStore { static Get(str, size = ColorType.Color1, arr = [0, 0, 0, 1]) { if (size === ColorType.Color1) { const color = ColorStore.store1[str]; if (color) return arr[0] = color[0], arr[1] = color[1], arr[2] = color[2], arr[3] = color[3], arr; const c = Color.parseColorString(str); if (c) { const data = [c.r / 255, c.g / 255, c.b / 255, c.opacity]; ColorStore.store1[str] = data, ColorStore.store255[str] = [c.r, c.g, c.b, c.opacity], arr[0] = data[0], arr[1] = data[1], arr[2] = data[2], arr[3] = data[3]; } return arr; } const color = ColorStore.store255[str]; if (color) return arr[0] = color[0], arr[1] = color[1], arr[2] = color[2], arr[3] = color[3], arr; const c = Color.parseColorString(str); return c && (ColorStore.store1[str] = [c.r / 255, c.g / 255, c.b / 255, c.opacity], ColorStore.store255[str] = [c.r, c.g, c.b, c.opacity], arr[0] = c.r, arr[1] = c.g, arr[2] = c.b, arr[3] = c.opacity), arr; } static Set(str, size, arr) { if (size === ColorType.Color1) { if (ColorStore.store1[str]) return; ColorStore.store1[str] = arr, ColorStore.store255[str] = [Math.floor(255 * arr[0]), Math.floor(255 * arr[1]), Math.floor(255 * arr[2]), Math.floor(255 * arr[3])]; } else { if (ColorStore.store255[str]) return; ColorStore.store255[str] = arr, ColorStore.store1[str] = [arr[0] / 255, arr[1] / 255, arr[2] / 255, arr[3]]; } } } ColorStore.store255 = {}, ColorStore.store1 = {}; function colorArrayToString(color, alphaChannel = !1) { return Array.isArray(color) && isNumber(color[0]) ? alphaChannel ? `rgb(${Math.round(color[0])},${Math.round(color[1])},${Math.round(color[2])},${color[3].toFixed(2)})` : `rgb(${Math.round(color[0])},${Math.round(color[1])},${Math.round(color[2])})` : color; } function interpolateColor(from, to, ratio, alphaChannel, cb) { if (Array.isArray(from) && !isNumber(from[0]) || Array.isArray(to) && !isNumber(to[0])) { return new Array(4).fill(0).map((_, index) => { var _a, _b; return _interpolateColor(isArray(from) ? null !== (_a = from[index]) && void 0 !== _a ? _a : from[0] : from, isArray(to) ? null !== (_b = to[index]) && void 0 !== _b ? _b : to[0] : to, ratio, alphaChannel); }); } return _interpolateColor(from, to, ratio, alphaChannel, cb); } function _interpolateColor(from, to, ratio, alphaChannel, cb) { if (!from || !to) return from && colorArrayToString(from) || to && colorArrayToString(to) || !1; let fromArray, toArray, fromGradient = !1, toGradient = !1; if (Array.isArray(from) ? fromArray = from : "string" == typeof from ? fromArray = ColorStore.Get(from, ColorType.Color255) : fromGradient = !0, Array.isArray(to) ? toArray = to : "string" == typeof to ? toArray = ColorStore.Get(to, ColorType.Color255) : toGradient = !0, fromGradient !== toGradient) { const gradient = fromGradient ? from : to, pure = fromGradient ? to : from, gradientFromPure = Object.assign(Object.assign({}, gradient), { stops: gradient.stops.map(v => Object.assign(Object.assign({}, v), { color: colorArrayToString(pure) })) }); return fromGradient ? interpolateColor(gradient, gradientFromPure, ratio, alphaChannel, cb) : interpolateColor(gradientFromPure, gradient, ratio, alphaChannel, cb); } if (fromGradient) { if (from.gradient === to.gradient) { const fc = from, tc = to, fromStops = fc.stops, toStops = tc.stops; if (fromStops.length !== toStops.length) return !1; if ("linear" === fc.gradient) return interpolateGradientLinearColor(fc, tc, ratio); if ("radial" === fc.gradient) return interpolateGradientRadialColor(fc, tc, ratio); if ("conical" === fc.gradient) return interpolateGradientConicalColor(fc, tc, ratio); } return !1; } cb && cb(fromArray, toArray); return colorArrayToString(interpolatePureColorArray(fromArray, toArray, ratio), alphaChannel); } function interpolateGradientLinearColor(fc, tc, ratio) { const fStops = fc.stops, tStops = tc.stops; return { gradient: "linear", x0: fc.x0 + (tc.x0 - fc.x0) * ratio, x1: fc.x1 + (tc.x1 - fc.x1) * ratio, y0: fc.y0 + (tc.y0 - fc.y0) * ratio, y1: fc.y1 + (tc.y1 - fc.y1) * ratio, stops: new Array(fStops.length).fill(0).map((_, i) => ({ color: colorStringInterpolationToStr(fStops[i].color, tStops[i].color, ratio), offset: fStops[i].offset + (tStops[i].offset - fStops[i].offset) * ratio })) }; } function interpolateGradientRadialColor(fc, tc, ratio) { const fStops = fc.stops, tStops = tc.stops; return { gradient: "radial", x0: fc.x0 + (tc.x0 - fc.x0) * ratio, x1: fc.x1 + (tc.x1 - fc.x1) * ratio, y0: fc.y0 + (tc.y0 - fc.y0) * ratio, y1: fc.y1 + (tc.y1 - fc.y1) * ratio, r0: fc.r0 + (tc.r0 - fc.r0) * ratio, r1: fc.r1 + (tc.r1 - fc.r1) * ratio, stops: new Array(fStops.length).fill(0).map((_, i) => ({ color: colorStringInterpolationToStr(fStops[i].color, tStops[i].color, ratio), offset: fStops[i].offset + (tStops[i].offset - fStops[i].offset) * ratio })) }; } function interpolateGradientConicalColor(fc, tc, ratio) { const fStops = fc.stops, tStops = tc.stops; return { gradient: "conical", startAngle: fc.startAngle + (tc.startAngle - fc.startAngle) * ratio, endAngle: fc.endAngle + (tc.endAngle - fc.endAngle) * ratio, x: fc.x + (tc.x - fc.x) * ratio, y: fc.y + (tc.y - fc.y) * ratio, stops: new Array(fStops.length).fill(0).map((_, i) => ({ color: colorStringInterpolationToStr(fStops[i].color, tStops[i].color, ratio), offset: fStops[i].offset + (tStops[i].offset - fStops[i].offset) * ratio })) }; } function interpolatePureColorArray(from, to, ratio) { return [from[0] + (to[0] - from[0]) * ratio, from[1] + (to[1] - from[1]) * ratio, from[2] + (to[2] - from[2]) * ratio, from[3] + (to[3] - from[3]) * ratio]; } function interpolatePureColorArrayToStr(from, to, ratio) { return `rgba(${from[0] + (to[0] - from[0]) * ratio},${from[1] + (to[1] - from[1]) * ratio},${from[2] + (to[2] - from[2]) * ratio},${from[3] + (to[3] - from[3]) * ratio})`; } const _fromColorRGB = [0, 0, 0, 0], _toColorRGB = [0, 0, 0, 0]; function colorStringInterpolationToStr(fromColor, toColor, ratio) { return ColorStore.Get(fromColor, ColorType.Color255, _fromColorRGB), ColorStore.Get(toColor, ColorType.Color255, _toColorRGB), `rgba(${Math.round(_fromColorRGB[0] + (_toColorRGB[0] - _fromColorRGB[0]) * ratio)},${Math.round(_fromColorRGB[1] + (_toColorRGB[1] - _fromColorRGB[1]) * ratio)},${Math.round(_fromColorRGB[2] + (_toColorRGB[2] - _fromColorRGB[2]) * ratio)},${_fromColorRGB[3] + (_toColorRGB[3] - _fromColorRGB[3]) * ratio})`; } class Generator { static GenAutoIncrementId() { return Generator.auto_increment_id++; } } Generator.auto_increment_id = 0; class FederatedEvent { get layerX() { return this.layer.x; } get layerY() { return this.layer.y; } get pageX() { return this.page.x; } get pageY() { return this.page.y; } get x() { return this.canvas.x; } get y() { return this.canvas.y; } get canvasX() { return this.canvas.x; } get canvasY() { return this.canvas.y; } get viewX() { return this.viewport.x; } get viewY() { return this.viewport.y; } constructor(manager) { this.bubbles = !0, this.cancelBubble = !0, this.cancelable = !1, this.composed = !1, this.defaultPrevented = !1, this.eventPhase = FederatedEvent.prototype.NONE, this.propagationStopped = !1, this.propagationImmediatelyStopped = !1, this.layer = { x: 0, y: 0 }, this.page = { x: 0, y: 0 }, this.canvas = { x: 0, y: 0 }, this.viewport = { x: 0, y: 0 }, this.NONE = 0, this.CAPTURING_PHASE = 1, this.AT_TARGET = 2, this.BUBBLING_PHASE = 3, this.manager = manager; } composedPath() { return !this.manager || this.path && this.path[this.path.length - 1] === this.target || (this.path = this.target ? this.manager.propagationPath(this.target) : []), this.composedDetailPath(), this.path; } composedDetailPath() { return this.pickParams && this.pickParams.graphic ? (this.detailPath = this.path.slice(), this._composedDetailPath(this.pickParams)) : this.detailPath = this.path.slice(), this.detailPath; } _composedDetailPath(params) { if (params && params.graphic) { const g = params.graphic; if (g.stage) { const path = g.stage.eventSystem.manager.propagationPath(g); this.detailPath.push(path), this._composedDetailPath(params.params); } } } preventDefault() { try { this.nativeEvent instanceof Event && this.nativeEvent.cancelable && this.nativeEvent.preventDefault(); } catch (err) { this.nativeEvent.preventDefault && isFunction(this.nativeEvent.preventDefault) && this.nativeEvent.preventDefault(); } this.defaultPrevented = !0; } stopImmediatePropagation() { this.propagationImmediatelyStopped = !0; } stopPropagation() { try { this.nativeEvent instanceof Event && this.nativeEvent.cancelable && this.nativeEvent.stopPropagation(); } catch (err) { this.nativeEvent.stopPropagation && isFunction(this.nativeEvent.stopPropagation) && this.nativeEvent.stopPropagation(); } this.propagationStopped = !0; } initEvent() {} initUIEvent() {} clone() { throw new Error("Method not implemented."); } } class CustomEvent extends FederatedEvent { constructor(eventName, object) { super(), this.type = eventName, this.detail = object; } } var UpdateTag; !function (UpdateTag) { UpdateTag[UpdateTag.NONE = 0] = "NONE", UpdateTag[UpdateTag.UPDATE_BOUNDS = 1] = "UPDATE_BOUNDS", UpdateTag[UpdateTag.UPDATE_SHAPE = 2] = "UPDATE_SHAPE", UpdateTag[UpdateTag.CLEAR_SHAPE = 253] = "CLEAR_SHAPE", UpdateTag[UpdateTag.UPDATE_SHAPE_AND_BOUNDS = 3] = "UPDATE_SHAPE_AND_BOUNDS", UpdateTag[UpdateTag.INIT = 179] = "INIT", UpdateTag[UpdateTag.CLEAR_BOUNDS = 254] = "CLEAR_BOUNDS", UpdateTag[UpdateTag.UPDATE_GLOBAL_MATRIX = 32] = "UPDATE_GLOBAL_MATRIX", UpdateTag[UpdateTag.CLEAR_GLOBAL_MATRIX = 223] = "CLEAR_GLOBAL_MATRIX", UpdateTag[UpdateTag.UPDATE_LOCAL_MATRIX = 16] = "UPDATE_LOCAL_MATRIX", UpdateTag[UpdateTag.CLEAR_LOCAL_MATRIX = 239] = "CLEAR_LOCAL_MATRIX", UpdateTag[UpdateTag.UPDATE_GLOBAL_LOCAL_MATRIX = 48] = "UPDATE_GLOBAL_LOCAL_MATRIX", UpdateTag[UpdateTag.UPDATE_PAINT = 64] = "UPDATE_PAINT", UpdateTag[UpdateTag.CLEAR_PAINT = 191] = "CLEAR_PAINT", UpdateTag[UpdateTag.UPDATE_LAYOUT = 128] = "UPDATE_LAYOUT", UpdateTag[UpdateTag.CLEAR_LAYOUT = 127] = "CLEAR_LAYOUT"; }(UpdateTag || (UpdateTag = {})); var IContainPointMode; !function (IContainPointMode) { IContainPointMode[IContainPointMode.GLOBAL = 1] = "GLOBAL", IContainPointMode[IContainPointMode.LOCAL = 16] = "LOCAL", IContainPointMode[IContainPointMode.GLOBAL_ACCURATE = 3] = "GLOBAL_ACCURATE", IContainPointMode[IContainPointMode.LOCAL_ACCURATE = 48] = "LOCAL_ACCURATE"; }(IContainPointMode || (IContainPointMode = {})); var AttributeUpdateType; !function (AttributeUpdateType) { AttributeUpdateType[AttributeUpdateType.INIT = 0] = "INIT", AttributeUpdateType[AttributeUpdateType.DEFAULT = 1] = "DEFAULT", AttributeUpdateType[AttributeUpdateType.STATE = 2] = "STATE", AttributeUpdateType[AttributeUpdateType.ANIMATE_BIND = 10] = "ANIMATE_BIND", AttributeUpdateType[AttributeUpdateType.ANIMATE_PLAY = 11] = "ANIMATE_PLAY", AttributeUpdateType[AttributeUpdateType.ANIMATE_START = 12] = "ANIMATE_START", AttributeUpdateType[AttributeUpdateType.ANIMATE_UPDATE = 13] = "ANIMATE_UPDATE", AttributeUpdateType[AttributeUpdateType.ANIMATE_END = 14] = "ANIMATE_END", AttributeUpdateType[AttributeUpdateType.TRANSLATE = 20] = "TRANSLATE", AttributeUpdateType[AttributeUpdateType.TRANSLATE_TO = 21] = "TRANSLATE_TO", AttributeUpdateType[AttributeUpdateType.SCALE = 22] = "SCALE", AttributeUpdateType[AttributeUpdateType.SCALE_TO = 23] = "SCALE_TO", AttributeUpdateType[AttributeUpdateType.ROTATE = 24] = "ROTATE", AttributeUpdateType[AttributeUpdateType.ROTATE_TO = 25] = "ROTATE_TO"; }(AttributeUpdateType || (AttributeUpdateType = {})); var Direction; !function (Direction) { Direction[Direction.ROW = 1] = "ROW", Direction[Direction.COLUMN = 2] = "COLUMN"; }(Direction || (Direction = {})); var CurveTypeEnum; !function (CurveTypeEnum) { CurveTypeEnum[CurveTypeEnum.CubicBezierCurve = 0] = "CubicBezierCurve", CurveTypeEnum[CurveTypeEnum.QuadraticBezierCurve = 1] = "QuadraticBezierCurve", CurveTypeEnum[CurveTypeEnum.ArcCurve = 2] = "ArcCurve", CurveTypeEnum[CurveTypeEnum.LineCurve = 3] = "LineCurve", CurveTypeEnum[CurveTypeEnum.EllipseCurve = 4] = "EllipseCurve", CurveTypeEnum[CurveTypeEnum.MoveCurve = 5] = "MoveCurve"; }(CurveTypeEnum || (CurveTypeEnum = {})); var BaseRenderContributionTime; !function (BaseRenderContributionTime) { BaseRenderContributionTime[BaseRenderContributionTime.beforeFillStroke = 0] = "beforeFillStroke", BaseRenderContributionTime[BaseRenderContributionTime.afterFillStroke = 1] = "afterFillStroke"; }(BaseRenderContributionTime || (BaseRenderContributionTime = {})); var AnimateStepType; !function (AnimateStepType) { AnimateStepType.wait = "wait", AnimateStepType.from = "from", AnimateStepType.to = "to", AnimateStepType.customAnimate = "customAnimate"; }(AnimateStepType || (AnimateStepType = {})); var AnimateStatus; !function (AnimateStatus) { AnimateStatus[AnimateStatus.INITIAL = 0] = "INITIAL", AnimateStatus[AnimateStatus.RUNNING = 1] = "RUNNING", AnimateStatus[AnimateStatus.PAUSED = 2] = "PAUSED", AnimateStatus[AnimateStatus.END = 3] = "END"; }(AnimateStatus || (AnimateStatus = {})); var STATUS; !function (STATUS) { STATUS[STATUS.INITIAL = 0] = "INITIAL", STATUS[STATUS.RUNNING = 1] = "RUNNING", STATUS[STATUS.PAUSE = 2] = "PAUSE"; }(STATUS || (STATUS = {})); class Easing { constructor() { } static linear(t) { return t; } static none() { return this.linear; } static get(amount) { if (amount < -1) { amount = -1; } else if (amount > 1) { amount = 1; } return function (t) { if (amount === 0) { return t; } if (amount < 0) { return t * (t * -amount + 1 + amount); } return t * ((2 - t) * amount + (1 - amount)); }; } static getPowIn(pow) { return function (t) { return Math.pow(t, pow); }; } static getPowOut(pow) { return function (t) { return 1 - Math.pow(1 - t, pow); }; } static getPowInOut(pow) { return function (t) { if ((t *= 2) < 1) { return 0.5 * Math.pow(t, pow); } return 1 - 0.5 * Math.abs(Math.pow(2 - t, pow)); }; } static getBackIn(amount) { return function (t) { return t * t * ((amount + 1) * t - amount); }; } static getBackOut(amount) { return function (t) { return --t * t * ((amount + 1) * t + amount) + 1; }; } static getBackInOut(amount) { amount *= 1.525; return function (t) { if ((t *= 2) < 1) { return 0.5 * (t * t * ((amount + 1) * t - amount)); } return 0.5 * ((t -= 2) * t * ((amount + 1) * t + amount) + 2); }; } static sineIn(t) { return 1 - Math.cos((t * Math.PI) / 2); } static sineOut(t) { return Math.sin((t * Math.PI) / 2); } static sineInOut(t) { return -(Math.cos(Math.PI * t) - 1) / 2; } static expoIn(t) { return t === 0 ? 0 : Math.pow(2, 10 * t - 10); } static expoOut(t) { return t === 1 ? 1 : 1 - Math.pow(2, -10 * t); } static expoInOut(t) { return t === 0 ? 0 : t === 1 ? 1 : t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2; } static circIn(t) { return -(Math.sqrt(1 - t * t) - 1); } static circOut(t) { return Math.sqrt(1 - --t * t); } static circInOut(t) { if ((t *= 2) < 1) { return -0.5 * (Math.sqrt(1 - t * t) - 1); } return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); } static bounceOut(t) { if (t < 1 / 2.75) { return 7.5625 * t * t; } else if (t < 2 / 2.75) { return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75; } else if (t < 2.5 / 2.75) { return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375; } return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375; } static bounceIn(t) { return 1 - Easing.bounceOut(1 - t); } static bounceInOut(t) { if (t < 0.5) { return Easing.bounceIn(t * 2) * 0.5; } return Easing.bounceOut(t * 2 - 1) * 0.5 + 0.5; } static getElasticIn(amplitude, period) { return function (t) { if (t === 0 || t === 1) { return t; } const s = (period / pi2) * Math.asin(1 / amplitude); return -(amplitude * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t - s) * pi2) / period)); }; } static getElasticOut(amplitude, period) { return function (t) { if (t === 0 || t === 1) { return t; } const s = (period / pi2) * Math.asin(1 / amplitude); return amplitude * Math.pow(2, -10 * t) * Math.sin(((t - s) * pi2) / period) + 1; }; } static getElasticInOut(amplitude, period) { return function (t) { const s = (period / pi2) * Math.asin(1 / amplitude); if ((t *= 2) < 1) { return -0.5 * (amplitude * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t - s) * pi2) / period)); } return amplitude * Math.pow(2, -10 * (t -= 1)) * Math.sin(((t - s) * pi2) / period) * 0.5 + 1; }; } static registerFunc(name, func) { Easing[name] = func; } } Easing.quadIn = Easing.getPowIn(2); Easing.quadOut = Easing.getPowOut(2); Easing.quadInOut = Easing.getPowInOut(2); Easing.cubicIn = Easing.getPowIn(3); Easing.cubicOut = Easing.getPowOut(3); Easing.cubicInOut = Easing.getPowInOut(3); Easing.quartIn = Easing.getPowIn(4); Easing.quartOut = Easing.getPowOut(4); Easing.quartInOut = Easing.getPowInOut(4); Easing.quintIn = Easing.getPowIn(5); Easing.quintOut = Easing.getPowOut(5); Easing.quintInOut = Easing.getPowInOut(5); Easing.backIn = Easing.getBackIn(1.7); Easing.backOut = Easing.getBackOut(1.7); Easing.backInOut = Easing.getBackInOut(1.7); Easing.elasticIn = Easing.getElasticIn(1, 0.3); Easing.elasticOut = Easing.getElasticOut(1, 0.3); Easing.elasticInOut = Easing.getElasticInOut(1, 0.3 * 1.5); Easing.easeInOutQuad = (t) => { if ((t /= 0.5) < 1) { return 0.5 * Math.pow(t, 2); } return -0.5 * ((t -= 2) * t - 2); }; Easing.easeOutElastic = (x) => { const c4 = (2 * Math.PI) / 3; return x === 0 ? 0 : x === 1 ? 1 : Math.pow(2, -10 * x) * Math.sin((x * 10 - 0.75) * c4) + 1; }; Easing.easeInOutElastic = (x) => { const c5 = (2 * Math.PI) / 4.5; return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? -(Math.pow(2, 20 * x - 10) * Math.sin((20 * x - 11.125) * c5)) / 2 : (Math.pow(2, -20 * x + 10) * Math.sin((20 * x - 11.125) * c5)) / 2 + 1; }; function flicker(t, n) { const step = 1 / n; let flag = 1; while (t > step) { t -= step; flag *= -1; } const v = (flag * t) / step; return v > 0 ? v : 1 + v; } for (let i = 0; i < 10; i++) { Easing[`flicker${i}`] = (t) => flicker(t, i); } for (let i = 2; i < 10; i++) { Easing[`aIn${i}`] = (t) => i * t * t + (1 - i) * t; } var Edge; !function (Edge) { Edge[Edge.Top = 1] = "Top", Edge[Edge.Right = 2] = "Right", Edge[Edge.Bottom = 4] = "Bottom", Edge[Edge.Left = 8] = "Left", Edge[Edge.ALL = 15] = "ALL"; }(Edge || (Edge = {})); const _paddingVec4 = [0, 0, 0, 0]; const parsePadding = padding => padding ? isArray(padding) ? 0 === padding.length ? 0 : 1 === padding.length ? padding[0] : 2 === padding.length ? (_paddingVec4[0] = padding[0], _paddingVec4[2] = padding[0], _paddingVec4[1] = padding[1], _paddingVec4[3] = padding[1], _paddingVec4) : padding : padding : 0; function pointInterpolation(pointA, pointB, ratio) { const { x: x, y: y } = pointAt(pointA.x, pointA.y, pointB.x, pointB.y, ratio), { x: x1, y: y1 } = pointAt(pointA.x1, pointA.y1, pointB.x1, pointB.y1, ratio), point = new Point(x, y, x1, y1); return point.defined = pointB.defined, point; } function pointsInterpolation(pointsA, pointsB, ratio) { if (!pointsA || !pointsB) return []; Array.isArray(pointsA) || (pointsA = [pointsA]), Array.isArray(pointsB) || (pointsB = [pointsB]); let points = []; if (pointsA.length > pointsB.length) { points = pointsB.map(point => { const p = new Point(point.x, point.y, point.x1, point.y1); return p.defined = point.defined, p; }); for (let i = 0; i < pointsB.length; i++) points[i] = pointInterpolation(pointsA[i], pointsB[i], ratio); } else { points = pointsB.map(point => { const p = new Point(point.x, point.y, point.x1, point.y1); return p.defined = point.defined, p; }); for (let i = 0; i < pointsA.length; i++) points[i] = pointInterpolation(pointsA[i], pointsB[i], ratio); } return points; } function interpolateNumber(from, to, ratio) { return from + (to - from) * ratio; } class InterpolateUpdateStore { constructor() { this.opacity = (key, from, to, ratio, step, target) => { target.attribute.opacity = interpolateNumber(from, to, ratio); }; this.baseOpacity = (key, from, to, ratio, step, target) => { target.attribute.baseOpacity = interpolateNumber(from, to, ratio); }; this.fillOpacity = (key, from, to, ratio, step, target) => { target.attribute.fillOpacity = interpolateNumber(from, to, ratio); }; this.strokeOpacity = (key, from, to, ratio, step, target) => { target.attribute.strokeOpacity = interpolateNumber(from, to, ratio); }; this.zIndex = (key, from, to, ratio, step, target) => { target.attribute.zIndex = interpolateNumber(from, to, ratio); }; this.backgroundOpacity = (key, from, to, ratio, step, target) => { target.attribute.backgroundOpacity = interpolateNumber(from, to, ratio); }; this.shadowOffsetX = (key, from, to, ratio, step, target) => { target.attribute.shadowOffsetX = interpolateNumber(from, to, ratio); }; this.shadowOffsetY = (key, from, to, ratio, step, target) => { target.attribute.shadowOffsetY = interpolateNumber(from, to, ratio); }; this.shadowBlur = (key, from, to, ratio, step, target) => { target.attribute.shadowBlur = interpolateNumber(from, to, ratio); }; this.fill = (key, from, to, ratio, step, target) => { target.attribute.fill = interpolateColor(from, to, ratio, false); }; this.fillPure = (key, from, to, ratio, step, target) => { target.attribute.fill = step.fromParsedProps.fill ? interpolatePureColorArrayToStr(step.fromParsedProps.fill, step.toParsedProps.fill, ratio) : step.toParsedProps.fill; }; this.stroke = (key, from, to, ratio, step, target) => { target.attribute.stroke = interpolateColor(from, to, ratio, false); }; this.strokePure = (key, from, to, ratio, step, target) => { target.attribute.stroke = step.fromParsedProps.stroke ? interpolatePureColorArrayToStr(step.fromParsedProps.stroke, step.toParsedProps.stroke, ratio) : step.toParsedProps.stroke; }; this.width = (key, from, to, ratio, step, target) => { target.attribute.width = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.height = (key, from, to, ratio, step, target) => { target.attribute.height = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.x = (key, from, to, ratio, step, target) => { target.attribute.x = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.y = (key, from, to, ratio, step, target) => { target.attribute.y = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.dx = (key, from, to, ratio, step, target) => { target.attribute.dx = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.dy = (key, from, to, ratio, step, target) => { target.attribute.dy = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.angle = (key, from, to, ratio, step, target) => { target.attribute.angle = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.scaleX = (key, from, to, ratio, step, target) => { target.attribute.scaleX = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.scaleY = (key, from, to, ratio, step, target) => { target.attribute.scaleY = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); target.addUpdatePositionTag(); }; this.lineWidth = (key, from, to, ratio, step, target) => { target.attribute.lineWidth = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.startAngle = (key, from, to, ratio, step, target) => { target.attribute.startAngle = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.endAngle = (key, from, to, ratio, step, target) => { target.attribute.endAngle = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.radius = (key, from, to, ratio, step, target) => { target.attribute.radius = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.outerRadius = (key, from, to, ratio, step, target) => { target.attribute.outerRadius = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.innerRadius = (key, from, to, ratio, step, target) => { target.attribute.innerRadius = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.size = (key, from, to, ratio, step, target) => { target.attribute.size = interpolateNumber(from, to, ratio); target.addUpdateBoundTag(); }; this.points = (key, from, to, ratio, step, target) => { target.attribute.points = pointsInterpolation(from, to, ratio); target.addUpdateBoundTag(); }; } } const interpolateUpdateStore = new InterpolateUpdateStore(); function commonInterpolateUpdate(key, from, to, ratio, step, target) { if (Number.isFinite(to) && Number.isFinite(from)) { target.attribute[key] = from + (to - from) * ratio; return true; } else if (Array.isArray(to) && Array.isArray(from) && to.length === from.length) { const nextList = []; let valid = true; for (let i = 0; i < to.length; i++) { const v = from[i]; const val = v + (to[i] - v) * ratio; if (!Number.isFinite(val)) { valid = false; break; } nextList.push(val); } if (valid) { target.attribute[key] = nextList; } return true; } return false; } const animateUpdateContext = { type: AttributeUpdateType.ANIMATE_UPDATE }; const animateBindContext = { type: AttributeUpdateType.ANIMATE_BIND }; const animateStartContext = { type: AttributeUpdateType.ANIMATE_START }; function getAnimationContext(type) { switch (type) { case AttributeUpdateType.ANIMATE_UPDATE: return animateUpdateContext; case AttributeUpdateType.ANIMATE_BIND: return animateBindContext; case AttributeUpdateType.ANIMATE_START: return animateStartContext; default: return { type }; } } function prepareAnimationFrameAttribute(target) { const transientTarget = target; if (!transientTarget.attribute) { transientTarget.attribute = {}; } if (transientTarget.attribute === transientTarget.baseAttributes) { transientTarget.detachAttributeFromBaseAttributes(); } transientTarget.attributeMayContainTransientAttrs = true; return transientTarget.attribute; } function commitAnimationFrameAttribute(target) { target.onAttributeUpdate(animateUpdateContext); } function applyAnimationFrameAttributes(target, attributes) { if (!attributes) { return; } const targetAttribute = prepareAnimationFrameAttribute(target); for (const key in attributes) { if (Object.prototype.hasOwnProperty.call(attributes, key)) { targetAttribute[key] = attributes[key]; } } commitAnimationFrameAttribute(target); } function applyAnimationFrameNumberAttributes(target, keys, from, to, ratio) { const targetAttribute = prepareAnimationFrameAttribute(target); for (let i = 0; i < keys.length; i++) { const key = keys[i]; targetAttribute[key] = from[key] + (to[key] - from[key]) * ratio; } commitAnimationFrameAttribute(target); } function applyAnimationTransientAttributes(target, attributes, type = AttributeUpdateType.ANIMATE_UPDATE) { if (!attributes) { return; } const context = getAnimationContext(type); target.applyAnimationTransientAttributes(attributes, false, context); } function applyAppearStartAttributes(target, attributes) { applyAnimationTransientAttributes(target, attributes, AttributeUpdateType.ANIMATE_BIND); } function noop() { } function includesKey$1(keys, key) { for (let i = 0; i < keys.length; i++) { if (keys[i] === key) { return true; } } return false; } let Step$1 = class Step { constructor(type, props, duration, easing) { var _a; this._startTime = 0; this._hasFirstRun = false; this._syncAttributeUpdate = () => { this.target.addUpdateShapeAndBoundsTag(); this.target.addUpdatePositionTag(); this.target.onAttributeUpdate({ type: AttributeUpdateType.ANIMATE_UPDATE }); }; this.type = type; this.props = props; this.duration = duration; if (easing) { this.easing = typeof easing === 'function' ? easing : (_a = Easing[easing]) !== null && _a !== void 0 ? _a : Easing.linear; } else { this.easing = Easing.linear; } if (type === 'wait') { this.onUpdate = noop; } this.id = Generator.GenAutoIncrementId(); this.syncAttributeUpdate = noop; } bind(target, animate) { this.target = target; this.animate = animate; this.onBind(); this.syncAttributeUpdate(); } append(step) { this.next = step; step.prev = this; step.setStartTime(this.getStartTime() + this.duration, false); } updateDownstreamStartTimes() { let currentStep = this.next; let currentStartTime = this._startTime + this.duration; while (currentStep) { currentStep.setStartTime(currentStartTime, false); currentStartTime += currentStep.duration; currentStep = currentStep.next; } this.animate.updateDuration(); } getLastProps() { if (this.prev) { return this.prev.props || {}; } return this.animate.getStartProps(); } setDuration(duration, updateDownstream = true) { this.duration = duration; if (updateDownstream) { this.updateDownstreamStartTimes(); } } getDuration() { return this.duration; } determineInterpolateUpdateFunction() { if (!this.props) { return; } const funcs = []; this.propKeys.forEach(key => { if (key === 'fill' || key === 'stroke') { const from = this.fromProps[key]; const to = this.props[key]; if (isString(from) && isString(to)) { const fromArray = ColorStore.Get(from, ColorType.Color255); const toArray = ColorStore.Get(to, ColorType.Color255); if (!this.fromParsedProps) { this.fromParsedProps = {}; } if (!this.toParsedProps) { this.toParsedProps = {}; } this.fromParsedProps[key] = fromArray; this.toParsedProps[key] = toArray; funcs.push(interpolateUpdateStore[key === 'fill' ? 'fillPure' : 'strokePure']); } else if (interpolateUpdateStore[key]) { funcs.push(interpolateUpdateStore[key]); } else { funcs.push(commonInterpolateUpdate); } } else if (interpolateUpdateStore[key]) { funcs.push(interpolateUpdateStore[key]); } else { funcs.push(commonInterpolateUpdate); } }); this.interpolateUpdateFunctions = funcs; } setStartTime(time, updateDownstream = true) { this._startTime = time; if (updateDownstream) { this.updateDownstreamStartTimes(); } } getStartTime() { return this._startTime; } onBind() { if (this.target.type === 'glyph') { this.syncAttributeUpdate = this._syncAttributeUpdate; } } runInterpolateUpdate(fromProps, toProps, ratio) { if (this.animate.interpolateUpdateFunction) { this.animate.interpolateUpdateFunction(fromProps, toProps, ratio, this, this.target); return; } const funcs = this.interpolateUpdateFunctions; const propKeys = this.propKeys; if (!funcs || !propKeys) { return; } for (let index = 0; index < funcs.length; index++) { const key = propKeys[index]; const fromValue = fromProps[key]; const toValue = toProps[key]; funcs[index](key, fromValue, toValue, ratio, this, this.target); } } onFirstRun() { } onStart() { if (!this._hasFirstRun) { this._hasFirstRun = true; this.fromProps = this.getLastProps(); const startProps = this.animate.getStartProps(); this.propKeys && this.propKeys.forEach(key => { var _a; this.fromProps[key] = (_a = this.fromProps[key]) !== null && _a !== void 0 ? _a : startProps[key]; }); this.determineInterpolateUpdateFunction(); this.tryPreventConflict(); this.trySyncStartProps(); this.onFirstRun(); } } tryPreventConflict() { const animate = this.animate; const target = this.target; const propKeys = this.propKeys; target.forEachTrackedAnimate((a) => { if (a === animate || a.priority > animate.priority || a.priority === Infinity) { return; } const fromProps = a.getStartProps(); let conflictKeys = null; for (let i = 0; i < propKeys.length; i++) { const key = propKeys[i]; if (fromProps[key] != null) { (conflictKeys !== null && conflictKeys !== void 0 ? conflictKeys : (conflictKeys = [])).push(key); } } if (conflictKeys) { a.preventAttrs(conflictKeys); } }); } removeKeysFromRecord(record, keys) { if (!record) { return record; } let hasBlockedKey = false; for (const key in record) { if (Object.prototype.hasOwnProperty.call(record, key) && includesKey$1(keys, key)) { hasBlockedKey = true; break; } } if (!hasBlockedKey) { return record; } const nextRecord = {}; for (const key in record) { if (Object.prototype.hasOwnProperty.call(record, key) && !includesKey$1(keys, key)) { nextRecord[key] = record[key]; } } return nextRecord; } deleteSelfAttr(key) { this.deleteSelfAttrs([key]); } deleteSelfAttrs(keys) { var _a; if (!(keys === null || keys === void 0 ? void 0 : keys.length)) { return; } this.props = this.removeKeysFromRecord(this.props, keys); this.fromProps = this.removeKeysFromRecord(this.fromProps, keys); this.fromParsedProps = this.removeKeysFromRecord(this.fromParsedProps, keys); this.toParsedProps = this.removeKeysFromRecord(this.toParsedProps, keys); if ((_a = this.propKeys) === null || _a === void 0 ? void 0 : _a.length) { const funcs = this.interpolateUpdateFunctions; let writeIndex = 0; for (let readIndex = 0; readIndex < this.propKeys.length; readIndex++) { const propKey = this.propKeys[readIndex]; if (includesKey$1(keys, propKey)) { continue; } if (writeIndex !== readIndex) { this.propKeys[writeIndex] = propKey; if (funcs) { funcs[writeIndex] = funcs[readIndex]; } } writeIndex++; } this.propKeys.length = writeIndex; if (funcs) { funcs.length = writeIndex; } } } trySyncStartProps() { this.propKeys.forEach(key => { this.fromProps[key] = this.animate.target.getComputedAttribute(key); }); } update(end, ratio, out) { this.onStart(); if (!this.props || !this.propKeys) { return; } const easedRatio = this.easing(ratio); this.runInterpolateUpdate(this.fromProps, this.props, easedRatio); this.onUpdate(end, easedRatio, out); this.syncAttributeUpdate(); } onUpdate(end, ratio, out) { } onEnd(cb) { if (cb) { this._endCb = cb; } else if (this._endCb) { this._endCb(this.animate, this); } } getEndProps() { return this.props; } getFromProps() { return this.fromProps; } getMergedEndProps() { return this.getEndProps(); } stop() { } release() { } }; class WaitStep extends Step$1 { constructor(type, props, duration, easing) { super(type, props, duration, easing); } onStart() { super.onStart(); const fromProps = this.getFromProps(); applyAnimationTransientAttributes(this.target, fromProps, AttributeUpdateType.ANIMATE_START); } update(end, ratio, out) { this.onStart(); } determineInterpolateUpdateFunction() { return; } } class DefaultTimeline extends EventEmitter { get animateCount() { return this._animateCount; } constructor() { super(); this.head = null; this.tail = null; this.animateMap = new Map(); this._animateCount = 0; this._playSpeed = 1; this._totalDuration = 0; this._startTime = 0; this._currentTime = 0; this._animationEndFlag = true; this.id = Generator.GenAutoIncrementId(); this.paused = false; } isRunning() { return !this.paused && this._animateCount > 0; } forEachAccessAnimate(cb) { let current = this.head; let index = 0; while (current) { const next = current.next; cb(current.animate, index); index++; current = next; } } addAnimate(animate) { const newNode = { animate, next: null, prev: null }; if (!this.head) { this.head = newNode; this.tail = newNode; } else { if (this.tail) { this.tail.next = newNode; newNode.prev = this.tail; this.tail = newNode; } } this.animateMap.set(animate, newNode); this._animateCount++; this._totalDuration = Math.max(this._totalDuration, animate.getStartTime() + animate.getDuration()); } pause() { this.paused = true; } resume() { this.paused = false; } tick(delta) { if (this.paused) { return; } if (this._animationEndFlag) { this._animationEndFlag = false; this.emit('animationStart'); } const scaledDelta = delta * this._playSpeed; this._currentTime += scaledDelta; this.forEachAccessAnimate((animate, i) => { if (animate.status === AnimateStatus.END) { this.removeAnimate(animate, true); } else if (animate.status === AnimateStatus.RUNNING || animate.status === AnimateStatus.INITIAL) { animate.advance(scaledDelta); } }); if (this._animateCount === 0) { this._animationEndFlag = true; this.emit('animationEnd'); } } clear() { this.forEachAccessAnimate(animate => { animate.release(); }); this.head = null; this.tail = null; this.animateMap.clear(); this._animateCount = 0; this._totalDuration = 0; } removeAnimate(animate, release = true) { const node = this.animateMap.get(animate); if (!node) { return; } if (release) { animate._onRemove && animate._onRemove.forEach(cb => cb()); animate.release(); } if (node.prev) { node.prev.next = node.next; } else { this.head = node.next; } if (node.next) { node.next.prev = node.prev; } else { this.tail = node.prev; } this.animateMap.delete(animate); this._animateCount--; if (animate.getStartTime() + animate.getDuration() >= this._totalDuration) { this.recalculateTotalDuration(); } return; } recalculateTotalDuration() { this._totalDuration = 0; this.forEachAccessAnimate(animate => { this._totalDuration = Math.max(this._totalDuration, animate.getStartTime() + animate.getDuration()); }); } getTotalDuration() { return this._totalDuration; } getPlaySpeed() { return this._playSpeed; } setPlaySpeed(speed) { this._playSpeed = speed; } getPlayState() { if (this.paused) { return 'paused'; } if (this.animateCount === 0) { return 'stopped'; } return 'playing'; } setStartTime(time) { this._startTime = time; } getStartTime() { return this._startTime; } getCurrentTime() { return this._currentTime; } setCurrentTime(time) { this._currentTime = time; } } const defaultTimeline = new DefaultTimeline(); defaultTimeline.isGlobal = true; class ACustomAnimate extends Step$1 { constructor(customFrom, customTo, duration, easing, params) { super('customAnimate', (customTo !== null && customTo !== void 0 ? customTo : {}), duration, easing); this.type = 'customAnimate'; this.customFrom = customFrom; this.params = params; this.from = customFrom; this.to = customTo; } update(end, ratio, out) { this.onStart(); if (!this.props || !this.propKeys) { return; } const easedRatio = this.easing(ratio); this.onUpdate(end, easedRatio, out); this.syncAttributeUpdate(); } setProps(props) { this.props = props; this.propKeys = Object.keys(props); this.animate.reSyncProps(); } } class AComponentAnimate extends ACustomAnimate { completeBind(animator) { this.setStartTime(0); this._animator && this._animator.start(); this.setDuration(animator.getDuration()); } stop() { this._animator && this._animator.stop(); } } class AStageAnimate extends ACustomAnimate { constructor(customFrom, customTo, duration, easing, params) { super(customFrom, customTo, duration, easing, params); this.willCallBeforeStageRender = true; this.willCallAfterStageRender = true; this.checkStatusAfterRender = true; this._beforeStageRender = () => { if (!this.willCallBeforeStageRender) { return; } this.willCallBeforeStageRender = false; const stage = this.target.stage; const canvas = stage.window.getContext().canvas.nativeCanvas; const outputCanvas = this.beforeStageRender(stage, canvas); if (outputCanvas) { this.renderToStage(stage, outputCanvas); } }; this._afterStageRender = () => { if (!this.willCallAfterStageRender) { return; } this.willCallAfterStageRender = false; const stage = this.target.stage; const canvas = stage.window.getContext().canvas.nativeCanvas; const outputCanvas = this.afterStageRender(stage, canvas); if (outputCanvas) { this.renderToStage(stage, outputCanvas); } if (this.checkStatusAfterRender && this.animate.status === AnimateStatus.END) { this.animate.timeline.removeAnimate(this.animate); } }; this.props = {}; } beforeStageRender(stage, canvas) { return false; } afterStageRender(stage, canvas) { return false; } onFirstRun() { super.onFirstRun(); this.target.stage.setBeforeRender(this._beforeStageRender); this.target.stage.setAfterRender(this._afterStageRender); this.target.stage.disableDirtyBounds(); } stop() { super.stop(); this.target.stage.removeBeforeRender(this._beforeStageRender); this.target.stage.removeAfterRender(this._afterStageRender); } onUpdate(end, ratio, out) { super.onUpdate(end, ratio, out); this.willCallBeforeStageRender = true; this.willCallAfterStageRender = true; } renderToStage(stage, canvas) { const stageCanvas = stage.window.getContext().canvas.nativeCanvas; const ctx = stageCanvas.getContext('2d'); if (!ctx) { return false; } ctx.clearRect(0, 0, stageCanvas.width, stageCanvas.height); ctx.drawImage(canvas, 0, 0); return stageCanvas; } } class FromTo extends ACustomAnimate { constructor(from, to, duration, easing, params) { super(from, to, duration, easing, params); this.from = from !== null && from !== void 0 ? from : {}; } applyTransientFromAttributes() { applyAnimationTransientAttributes(this.target, this.from, AttributeUpdateType.ANIMATE_START); } onBind() { var _a, _b, _c; super.onBind(); Object.keys(this.from).forEach(key => { if (this.props[key] == null) { this.props[key] =