@visactor/vrender-animate
Version:
This module provides a graph-based animation system for VRender.
138 lines (132 loc) • 6.07 kB
JavaScript
import { ColorStore, ColorType, Generator } from "@visactor/vrender-core";
import { Easing } from "./utils/easing";
import { commonInterpolateUpdate, interpolateUpdateStore } from "./interpolate/store";
import { isString } from "@visactor/vutils";
function noop() {}
export class Step {
constructor(type, props, duration, easing) {
var _a;
this._startTime = 0, this._hasFirstRun = !1, this._syncAttributeUpdate = () => {
this.target.setAttributes(this.target.attribute);
}, 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);
}
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;
this.target.animates.forEach((a => {
if (a === animate || a.priority > animate.priority || a.priority === 1 / 0) return;
const fromProps = a.getStartProps();
this.propKeys.forEach((key => {
null != fromProps[key] && a.preventAttr(key);
}));
}));
}
deleteSelfAttr(key) {
var _a;
delete this.props[key], this.fromProps && delete this.fromProps[key];
const index = this.propKeys.indexOf(key);
-1 !== index && (this.propKeys.splice(index, 1), null === (_a = this.interpolateUpdateFunctions) || void 0 === _a || _a.splice(index, 1));
}
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.animate.interpolateUpdateFunction ? this.animate.interpolateUpdateFunction(this.fromProps, this.props, easedRatio, this, this.target) : this.interpolateUpdateFunctions.forEach(((func, index) => {
if (!this.animate.validAttr(this.propKeys[index])) return;
const key = this.propKeys[index];
func(key, this.fromProps[key], this.props[key], easedRatio, this, this.target);
})), this.onUpdate(end, easedRatio, out), this.syncAttributeUpdate();
}
onUpdate(end, ratio, out) {}
onEnd(cb) {
this.target.setAttributes(this.props), cb ? this._endCb = cb : this._endCb && this._endCb(this.animate, this);
}
getEndProps() {
return this.props;
}
getFromProps() {
return this.fromProps;
}
getMergedEndProps() {
return this.getEndProps();
}
stop() {}
}
export class WaitStep extends Step {
constructor(type, props, duration, easing) {
super(type, props, duration, easing);
}
onStart() {
super.onStart();
}
onFirstRun() {
const fromProps = this.getFromProps();
this.target.setAttributes(fromProps);
}
update(end, ratio, out) {
this.onStart();
}
determineInterpolateUpdateFunction() {}
}
//# sourceMappingURL=step.js.map