UNPKG

@visactor/vrender-animate

Version:

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

182 lines (172 loc) 8.3 kB
import { ColorStore, ColorType } from "@visactor/vrender-core/color-string"; import { Generator } from "@visactor/vrender-core/common/generator"; import { AttributeUpdateType } from "@visactor/vrender-core/event/constant"; import { Easing } from "./utils/easing"; import { commonInterpolateUpdate, interpolateUpdateStore } from "./interpolate/store"; import { isString } from "@visactor/vutils"; import { applyAnimationTransientAttributes } from "./custom/transient"; function noop() {} function includesKey(keys, key) { for (let i = 0; i < keys.length; i++) if (keys[i] === key) return !0; return !1; } export class Step { constructor(type, props, duration, easing) { var _a; this._startTime = 0, this._hasFirstRun = !1, this._syncAttributeUpdate = () => { this.target.addUpdateShapeAndBoundsTag(), this.target.addUpdatePositionTag(), this.target.onAttributeUpdate({ type: AttributeUpdateType.ANIMATE_UPDATE }); }, this.type = type, this.props = props, this.duration = duration, this.easing = easing ? "function" == typeof easing ? easing : null !== (_a = Easing[easing]) && void 0 !== _a ? _a : Easing.linear : Easing.linear, "wait" === type && (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, !1); } updateDownstreamStartTimes() { let currentStep = this.next, currentStartTime = this._startTime + this.duration; for (;currentStep; ) currentStep.setStartTime(currentStartTime, !1), currentStartTime += currentStep.duration, currentStep = currentStep.next; this.animate.updateDuration(); } getLastProps() { return this.prev ? this.prev.props || {} : this.animate.getStartProps(); } setDuration(duration, updateDownstream = !0) { this.duration = duration, updateDownstream && this.updateDownstreamStartTimes(); } getDuration() { return this.duration; } determineInterpolateUpdateFunction() { if (!this.props) return; const funcs = []; this.propKeys.forEach((key => { if ("fill" === key || "stroke" === key) { const from = this.fromProps[key], to = this.props[key]; if (isString(from) && isString(to)) { const fromArray = ColorStore.Get(from, ColorType.Color255), toArray = ColorStore.Get(to, ColorType.Color255); this.fromParsedProps || (this.fromParsedProps = {}), this.toParsedProps || (this.toParsedProps = {}), this.fromParsedProps[key] = fromArray, this.toParsedProps[key] = toArray, funcs.push(interpolateUpdateStore["fill" === key ? "fillPure" : "strokePure"]); } else interpolateUpdateStore[key] ? funcs.push(interpolateUpdateStore[key]) : funcs.push(commonInterpolateUpdate); } else interpolateUpdateStore[key] ? funcs.push(interpolateUpdateStore[key]) : funcs.push(commonInterpolateUpdate); })), this.interpolateUpdateFunctions = funcs; } setStartTime(time, updateDownstream = !0) { this._startTime = time, updateDownstream && this.updateDownstreamStartTimes(); } getStartTime() { return this._startTime; } onBind() { "glyph" === this.target.type && (this.syncAttributeUpdate = this._syncAttributeUpdate); } runInterpolateUpdate(fromProps, toProps, ratio) { if (this.animate.interpolateUpdateFunction) return void this.animate.interpolateUpdateFunction(fromProps, toProps, ratio, this, this.target); const funcs = this.interpolateUpdateFunctions, propKeys = this.propKeys; if (funcs && propKeys) for (let index = 0; index < funcs.length; index++) { const key = propKeys[index], fromValue = fromProps[key], toValue = toProps[key]; funcs[index](key, fromValue, toValue, ratio, this, this.target); } } onFirstRun() {} onStart() { if (!this._hasFirstRun) { this._hasFirstRun = !0, this.fromProps = this.getLastProps(); const startProps = this.animate.getStartProps(); this.propKeys && this.propKeys.forEach((key => { var _a; this.fromProps[key] = null !== (_a = this.fromProps[key]) && void 0 !== _a ? _a : startProps[key]; })), this.determineInterpolateUpdateFunction(), this.tryPreventConflict(), this.trySyncStartProps(), this.onFirstRun(); } } tryPreventConflict() { const animate = this.animate, target = this.target, propKeys = this.propKeys; target.forEachTrackedAnimate((a => { if (a === animate || a.priority > animate.priority || a.priority === 1 / 0) return; const fromProps = a.getStartProps(); let conflictKeys = null; for (let i = 0; i < propKeys.length; i++) { const key = propKeys[i]; null != fromProps[key] && (null != conflictKeys ? conflictKeys : conflictKeys = []).push(key); } conflictKeys && a.preventAttrs(conflictKeys); })); } removeKeysFromRecord(record, keys) { if (!record) return record; let hasBlockedKey = !1; for (const key in record) if (Object.prototype.hasOwnProperty.call(record, key) && includesKey(keys, key)) { hasBlockedKey = !0; break; } if (!hasBlockedKey) return record; const nextRecord = {}; for (const key in record) Object.prototype.hasOwnProperty.call(record, key) && !includesKey(keys, key) && (nextRecord[key] = record[key]); return nextRecord; } deleteSelfAttr(key) { this.deleteSelfAttrs([ key ]); } deleteSelfAttrs(keys) { var _a; if ((null == keys ? void 0 : keys.length) && (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), null === (_a = this.propKeys) || void 0 === _a ? 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]; includesKey(keys, propKey) || (writeIndex !== readIndex && (this.propKeys[writeIndex] = propKey, funcs && (funcs[writeIndex] = funcs[readIndex])), writeIndex++); } this.propKeys.length = writeIndex, funcs && (funcs.length = writeIndex); } } trySyncStartProps() { this.propKeys.forEach((key => { this.fromProps[key] = this.animate.target.getComputedAttribute(key); })); } update(end, ratio, out) { if (this.onStart(), !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) { cb ? this._endCb = cb : this._endCb && this._endCb(this.animate, this); } getEndProps() { return this.props; } getFromProps() { return this.fromProps; } getMergedEndProps() { return this.getEndProps(); } stop() {} release() {} } export class WaitStep extends Step { 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() {} } //# sourceMappingURL=step.js.map