UNPKG

@visactor/vrender-animate

Version:

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

234 lines (230 loc) 17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.AnimateExecutor = void 0; const vutils_1 = require("@visactor/vutils"); class AnimateExecutor { static registerBuiltInAnimate(name, animate) { AnimateExecutor.builtInAnimateMap[name] = animate; } constructor(target) { this._animates = [], this._startCallbacks = [], this._endCallbacks = [], this._started = !1, this._activeCount = 0, this._target = target; } onStart(cb) { cb ? (this._startCallbacks.push(cb), this._started && this._activeCount > 0 && cb()) : this._startCallbacks.forEach((cb => { cb(); })); } onEnd(cb) { cb ? this._endCallbacks.push(cb) : this._endCallbacks.forEach((cb => { cb(); })); } _trackAnimation(animate) { this._animates.push(animate), this._activeCount++, 1 !== this._activeCount || this._started || (this._started = !0, this.onStart()), animate.onEnd((() => { this._activeCount--; const index = this._animates.indexOf(animate); index >= 0 && this._animates.splice(index, 1), 0 === this._activeCount && this._started && (this._started = !1, this.onEnd()); })); } parseParams(params, isTimeline, child) { var _a, _b; const totalTime = this.resolveValue(params.totalTime, void 0, void 0), startTime = this.resolveValue(params.startTime, void 0, 0), parsedParams = Object.assign({}, params); parsedParams.oneByOneDelay = 0, parsedParams.startTime = startTime, parsedParams.totalTime = totalTime; const oneByOne = this.resolveValue(params.oneByOne, child, !1); if (isTimeline) { const timeSlices = parsedParams.timeSlices; (0, vutils_1.isArray)(timeSlices) || (parsedParams.timeSlices = [ timeSlices ]); let sliceTime = 0; parsedParams.timeSlices = parsedParams.timeSlices.map((slice => { const delay = this.resolveValue(slice.delay, child, 0), delayAfter = this.resolveValue(slice.delayAfter, child, 0), duration = this.resolveValue(slice.duration, child, 300); return sliceTime += delay + duration + delayAfter, Object.assign(Object.assign({}, slice), { delay: delay, delayAfter: delayAfter, duration: duration }); })); let oneByOneDelay = 0; oneByOne && (oneByOneDelay = "number" == typeof oneByOne ? oneByOne : oneByOne ? sliceTime : 0), parsedParams.oneByOneDelay = oneByOneDelay; let scale = 1; if (totalTime) { const _totalTime = sliceTime + oneByOneDelay * (this._target.count - 2); scale = totalTime ? totalTime / _totalTime : 1; } parsedParams.timeSlices = parsedParams.timeSlices.map((slice => { let effects = slice.effects; return Array.isArray(effects) || (effects = [ effects ]), Object.assign(Object.assign({}, slice), { delay: slice.delay * scale, delayAfter: slice.delayAfter * scale, duration: slice.duration * scale, effects: effects.map((effect => { var _a, _b; const custom = null !== (_a = effect.custom) && void 0 !== _a ? _a : AnimateExecutor.builtInAnimateMap[null !== (_b = effect.type) && void 0 !== _b ? _b : "fromTo"], customType = custom && (0, vutils_1.isFunction)(custom) ? /^class\s/.test(Function.prototype.toString.call(custom)) ? 1 : 2 : 0; return Object.assign(Object.assign({}, effect), { custom: custom, customType: customType }); })) }); })), parsedParams.oneByOneDelay = oneByOneDelay * scale, parsedParams.startTime = startTime * scale; } else { const delay = this.resolveValue(params.delay, child, 0), delayAfter = this.resolveValue(params.delayAfter, child, 0), duration = this.resolveValue(params.duration, child, 300); let oneByOneDelay = 0; oneByOne && (oneByOneDelay = "number" == typeof oneByOne ? oneByOne : oneByOne ? delay + delayAfter + duration : 0), parsedParams.oneByOneDelay = oneByOneDelay, parsedParams.custom = null !== (_a = params.custom) && void 0 !== _a ? _a : AnimateExecutor.builtInAnimateMap[null !== (_b = params.type) && void 0 !== _b ? _b : "fromTo"]; const customType = parsedParams.custom && (0, vutils_1.isFunction)(parsedParams.custom) ? /^class\s/.test(Function.prototype.toString.call(parsedParams.custom)) ? 1 : 2 : 0; if (parsedParams.customType = customType, totalTime) { const _totalTime = delay + delayAfter + duration + oneByOneDelay * (this._target.count - 2), scale = totalTime ? totalTime / _totalTime : 1; parsedParams.delay = delay * scale, parsedParams.delayAfter = delayAfter * scale, parsedParams.duration = duration * scale, parsedParams.oneByOneDelay = oneByOneDelay * scale, parsedParams.startTime = startTime; } } return parsedParams; } execute(params) { Array.isArray(params) ? params.forEach((param => this._execute(param))) : this._execute(params); } _execute(params) { if (params.selfOnly) return this._executeItem(params, this._target, 0, 1); const isTimeline = "timeSlices" in params; let filteredChildren; isTimeline && params.partitioner && (filteredChildren = (null != filteredChildren ? filteredChildren : this._target.getChildren()).filter((child => { var _a, _b; return params.partitioner(null === (_b = null === (_a = child.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], child, {}); }))), isTimeline && params.sort && (filteredChildren = null != filteredChildren ? filteredChildren : this._target.getChildren(), filteredChildren.sort(((a, b) => { var _a, _b, _c, _d; return params.sort(null === (_b = null === (_a = a.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], null === (_d = null === (_c = b.context) || void 0 === _c ? void 0 : _c.data) || void 0 === _d ? void 0 : _d[0], a, b, {}); }))); const cb = isTimeline ? (child, index, count) => { const parsedParams = this.parseParams(params, isTimeline, child), animate = this.executeTimelineItem(parsedParams, child, index, count); animate && this._trackAnimation(animate); } : (child, index, count) => { const parsedParams = this.parseParams(params, isTimeline, child), animate = this.executeTypeConfigItem(parsedParams, child, index, count); animate && this._trackAnimation(animate); }; filteredChildren ? filteredChildren.forEach(((child, index) => cb(child, index, filteredChildren.length))) : this._target.count <= 1 ? cb(this._target, 0, 1) : this._target.forEachChildren(((child, index) => cb(child, index, this._target.count - 1))); } executeTypeConfigItem(params, graphic, index, count) { var _a, _b, _c, _d, _e, _f, _g, _h; const {type: type = "fromTo", channel: channel, customParameters: customParameters, easing: easing = "linear", delay: delay = 0, delayAfter: delayAfter = 0, duration: duration = 300, startTime: startTime = 0, oneByOneDelay: oneByOneDelay = 0, loop: loop, bounce: bounce, priority: priority = 0, options: options, custom: custom, customType: customType, controlOptions: controlOptions} = params, animate = graphic.animate(); animate.priority = priority; const delayValue = (0, vutils_1.isFunction)(delay) ? delay(null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], graphic, {}) : delay, datum = null === (_d = null === (_c = graphic.context) || void 0 === _c ? void 0 : _c.data) || void 0 === _d ? void 0 : _d[0], indexKey = null === (_e = graphic.context) || void 0 === _e ? void 0 : _e.indexKey; datum && indexKey && (index = null !== (_f = datum[indexKey]) && void 0 !== _f ? _f : index), animate.startAt(startTime); const wait = index * oneByOneDelay + delayValue; wait > 0 && animate.wait(wait); let parsedFromProps = null, props = params.to, from = params.from; props || (parsedFromProps || (parsedFromProps = this.createPropsFromChannel(channel, graphic)), props = parsedFromProps.props), from || (parsedFromProps || (parsedFromProps = this.createPropsFromChannel(channel, graphic)), from = parsedFromProps.from), this._handleRunAnimate(animate, custom, customType, from, props, duration, easing, customParameters, controlOptions, options, type, graphic); let totalDelay = 0; oneByOneDelay && (totalDelay = oneByOneDelay * (count - index - 1)); const delayAfterValue = (0, vutils_1.isFunction)(delayAfter) ? delayAfter(null === (_h = null === (_g = graphic.context) || void 0 === _g ? void 0 : _g.data) || void 0 === _h ? void 0 : _h[0], graphic, {}) : delayAfter; return delayAfterValue > 0 && (totalDelay += delayAfterValue), totalDelay > 0 && animate.wait(totalDelay), loop && loop > 0 && animate.loop(loop), bounce && animate.bounce(!0), animate; } _handleRunAnimate(animate, custom, customType, from, props, duration, easing, customParameters, controlOptions, options, type, graphic) { var _a, _b, _c, _d; if (custom && customType) { const customParams = Object.assign({ width: graphic.stage.width, height: graphic.stage.height, group: this._target.parent }, this.resolveValue(customParameters, graphic)), objOptions = (0, vutils_1.isFunction)(options) ? options.call(null, null !== (_b = customParams && (null === (_a = customParams.data) || void 0 === _a ? void 0 : _a[0])) && void 0 !== _b ? _b : null === (_d = null === (_c = graphic.context) || void 0 === _c ? void 0 : _c.data) || void 0 === _d ? void 0 : _d[0], graphic, customParams) : options; customParams.options = objOptions, customParams.controlOptions = controlOptions, 1 === customType ? this.createCustomAnimation(animate, custom, from, props, duration, easing, customParams) : 2 === customType && this.createCustomInterpolatorAnimation(animate, custom, props, duration, easing, customParams); } else "to" === type ? animate.to(props, duration, easing) : "from" === type && animate.from(props, duration, easing); } executeTimelineItem(params, graphic, index, count) { var _a, _b, _c, _d; const {timeSlices: timeSlices, startTime: startTime = 0, loop: loop, bounce: bounce, oneByOneDelay: oneByOneDelay, priority: priority, controlOptions: controlOptions} = params, datum = null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], indexKey = null === (_c = graphic.context) || void 0 === _c ? void 0 : _c.indexKey; datum && indexKey && (index = null !== (_d = datum[indexKey]) && void 0 !== _d ? _d : index); const animate = graphic.animate(); animate.priority = priority, animate.startAt(startTime), animate.wait(index * oneByOneDelay), loop && loop > 0 && animate.loop(loop), bounce && animate.bounce(!0); return (Array.isArray(timeSlices) ? timeSlices : [ timeSlices ]).forEach((slice => { this.applyTimeSliceToAnimate(slice, animate, graphic, controlOptions); })), oneByOneDelay && animate.wait(oneByOneDelay * (count - index - 1)), animate; } applyTimeSliceToAnimate(slice, animate, graphic, controlOptions) { var _a, _b, _c, _d; const {effects: effects, duration: duration = 300, delay: delay = 0, delayAfter: delayAfter = 0} = slice, delayValue = (0, vutils_1.isFunction)(delay) ? delay(null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], graphic, {}) : delay, delayAfterValue = (0, vutils_1.isFunction)(delayAfter) ? delayAfter(null === (_d = null === (_c = graphic.context) || void 0 === _c ? void 0 : _c.data) || void 0 === _d ? void 0 : _d[0], graphic, {}) : delayAfter; delayValue > 0 && animate.wait(delayValue); (Array.isArray(effects) ? effects : [ effects ]).forEach((effect => { var _a; const {type: type = "fromTo", channel: channel, customParameters: customParameters, easing: easing = "linear", options: options} = effect; let parsedFromProps = null, props = effect.to, from = effect.from; props || (parsedFromProps || (parsedFromProps = this.createPropsFromChannel(channel, graphic)), props = parsedFromProps.props), from || (parsedFromProps || (parsedFromProps = this.createPropsFromChannel(channel, graphic)), from = parsedFromProps.from); const custom = null !== (_a = effect.custom) && void 0 !== _a ? _a : AnimateExecutor.builtInAnimateMap[type], customType = effect.customType; this._handleRunAnimate(animate, custom, customType, from, props, duration, easing, customParameters, controlOptions, options, type, graphic); })), delayAfterValue > 0 && animate.wait(delayAfterValue); } createCustomInterpolatorAnimation(animate, interpolator, props, duration, easing, customParams) { const from = {}, to = props; Object.keys(to).forEach((key => { from[key] = animate.target.getComputedAttribute(key); })), animate.interpolateUpdateFunction = (from, to, ratio, step, target) => { interpolator(ratio, from, to, step, target, animate.target, customParams); }, animate.to(props, duration, easing); } createCustomAnimation(animate, CustomAnimateConstructor, from, props, duration, easing, customParams) { const customAnimate = new CustomAnimateConstructor(from, props, duration, easing, customParams); animate.play(customAnimate); } createPropsFromChannel(channel, graphic) { const props = {}; let from = null; return channel ? (Array.isArray(channel) ? channel.forEach((key => { var _a, _b; const value = null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.diffAttrs) || void 0 === _b ? void 0 : _b[key]; void 0 !== value && (props[key] = value); })) : Object.keys(channel).forEach((key => { var _a, _b, _c, _d; const config = channel[key]; void 0 !== config.to && ("function" == typeof config.to ? props[key] = config.to(null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], graphic, {}) : props[key] = config.to), void 0 !== config.from && (from || (from = {}), "function" == typeof config.from ? from[key] = config.from(null === (_d = null === (_c = graphic.context) || void 0 === _c ? void 0 : _c.data) || void 0 === _d ? void 0 : _d[0], graphic, {}) : from[key] = config.from); })), { from: from, props: props }) : { from: from, props: props }; } resolveValue(value, graphic, defaultValue) { var _a, _b; return void 0 === value ? defaultValue : "function" == typeof value && graphic ? value(null === (_b = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0], graphic, {}) : value; } executeItem(params, graphic, index = 0, count = 1) { return Array.isArray(params) ? params.map((param => this._executeItem(param, graphic, index, count))).filter(Boolean) : [ this._executeItem(params, graphic, index, count) ].filter(Boolean); } _executeItem(params, graphic, index = 0, count = 1) { if (!graphic) return null; const isTimeline = "timeSlices" in params; let animate = null; const parsedParams = this.parseParams(params, isTimeline); return animate = isTimeline ? this.executeTimelineItem(parsedParams, graphic, index, count) : this.executeTypeConfigItem(parsedParams, graphic, index, count), animate && this._trackAnimation(animate), animate; } stop(type) { for (;this._animates.length > 0; ) { const animate = this._animates.pop(); null == animate || animate.stop(type); } this._animates = [], this._activeCount = 0, this._started && (this._started = !1, this.onEnd()); } } exports.AnimateExecutor = AnimateExecutor, AnimateExecutor.builtInAnimateMap = {}; //# sourceMappingURL=animate-executor.js.map