@visactor/vrender-animate
Version:
This module provides a graph-based animation system for VRender.
109 lines (104 loc) • 8.21 kB
JavaScript
import { clamp, isValidNumber, Point } from "@visactor/vutils";
import { pointInterpolation } from "@visactor/vrender-core/interpolate";
import { ACustomAnimate } from "./custom-animate";
import { applyAnimationFrameAttributes, applyAnimationTransientAttributes } from "./transient";
import { commitAnimationStaticAttrs } from "./static-truth";
export class TagPointsUpdate extends ACustomAnimate {
constructor(from, to, duration, easing, params) {
var _a, _b;
super(from, to, duration, easing, params), this.newPointAnimateType = null !== (_a = null == params ? void 0 : params.newPointAnimateType) && void 0 !== _a ? _a : "grow",
this.clipRangeByDimension = null !== (_b = null == params ? void 0 : params.clipRangeByDimension) && void 0 !== _b ? _b : "x";
}
getPoints(attribute, cache = !1) {
if (attribute.points) return attribute.points;
if (attribute.segments) {
const points = [];
return this.segmentsCache || (this.segmentsCache = []), attribute.segments.map((segment => {
var _a, _b;
segment.points && points.push(...segment.points), cache && this.segmentsCache.push(null !== (_b = null === (_a = segment.points) || void 0 === _a ? void 0 : _a.length) && void 0 !== _b ? _b : 0);
})), points;
}
return [];
}
onBind() {
var _a, _b, _c, _d, _e;
super.onBind();
const currentAttribute = this.target.attribute, explicitFrom = null !== (_a = this.from) && void 0 !== _a ? _a : {}, explicitTo = null !== (_b = this.to) && void 0 !== _b ? _b : {}, context = null !== (_c = this.target.context) && void 0 !== _c ? _c : {}, contextFinalAttrs = null !== (_d = context.finalAttrs) && void 0 !== _d ? _d : {}, contextDiffAttrs = null !== (_e = context.diffAttrs) && void 0 !== _e ? _e : {}, finalAttribute = this.target.getFinalAttribute();
this.from = {}, this.to = {}, Object.prototype.hasOwnProperty.call(explicitFrom, "points") ? this.from.points = explicitFrom.points : Object.prototype.hasOwnProperty.call(currentAttribute, "points") && (this.from.points = currentAttribute.points),
Object.prototype.hasOwnProperty.call(explicitFrom, "segments") ? this.from.segments = explicitFrom.segments : Object.prototype.hasOwnProperty.call(currentAttribute, "segments") && (this.from.segments = currentAttribute.segments),
Object.prototype.hasOwnProperty.call(explicitTo, "points") ? this.to.points = explicitTo.points : Object.prototype.hasOwnProperty.call(contextFinalAttrs, "points") ? this.to.points = contextFinalAttrs.points : Object.prototype.hasOwnProperty.call(contextDiffAttrs, "points") ? this.to.points = contextDiffAttrs.points : finalAttribute && Object.prototype.hasOwnProperty.call(finalAttribute, "points") && (this.to.points = finalAttribute.points),
Object.prototype.hasOwnProperty.call(explicitTo, "segments") ? this.to.segments = explicitTo.segments : Object.prototype.hasOwnProperty.call(contextFinalAttrs, "segments") ? this.to.segments = contextFinalAttrs.segments : Object.prototype.hasOwnProperty.call(contextDiffAttrs, "segments") ? this.to.segments = contextDiffAttrs.segments : finalAttribute && Object.prototype.hasOwnProperty.call(finalAttribute, "segments") && (this.to.segments = finalAttribute.segments),
this.props = this.to;
const originFromPoints = this.getPoints(this.from), originToPoints = this.getPoints(this.to, !0);
this.fromPoints = originFromPoints ? Array.isArray(originFromPoints) ? originFromPoints : [ originFromPoints ] : [],
this.toPoints = originToPoints ? Array.isArray(originToPoints) ? originToPoints : [ originToPoints ] : [];
const tagMap = new Map;
this.fromPoints.forEach((point => {
point.context && tagMap.set(point.context, point);
}));
let firstMatchedPoint, lastMatchedPoint, firstMatchedIndex = 1 / 0, lastMatchedIndex = -1 / 0;
for (let i = 0; i < this.toPoints.length; i += 1) if (tagMap.has(this.toPoints[i].context)) {
firstMatchedIndex = i, firstMatchedPoint = tagMap.get(this.toPoints[i].context);
break;
}
for (let i = this.toPoints.length - 1; i >= 0; i -= 1) if (tagMap.has(this.toPoints[i].context)) {
lastMatchedIndex = i, lastMatchedPoint = tagMap.get(this.toPoints[i].context);
break;
}
"clip" === this.newPointAnimateType && 0 !== this.toPoints.length && (Number.isFinite(lastMatchedIndex) ? (this.clipRange = this.toPoints[lastMatchedIndex][this.clipRangeByDimension] / this.toPoints[this.toPoints.length - 1][this.clipRangeByDimension],
1 === this.clipRange && (this.shrinkClipRange = this.toPoints[lastMatchedIndex][this.clipRangeByDimension] / this.fromPoints[this.fromPoints.length - 1][this.clipRangeByDimension]),
isValidNumber(this.clipRange) ? this.clipRange = clamp(this.clipRange, 0, 1) : this.clipRange = 0) : this.clipRange = 0);
let prevMatchedPoint = this.toPoints[0];
this.interpolatePoints = this.toPoints.map(((point, index) => {
const matchedPoint = tagMap.get(point.context);
return matchedPoint ? (prevMatchedPoint = matchedPoint, [ matchedPoint, point ]) : "appear" === this.newPointAnimateType || "clip" === this.newPointAnimateType ? [ point, point ] : index < firstMatchedIndex && firstMatchedPoint ? [ firstMatchedPoint, point ] : index > lastMatchedIndex && lastMatchedPoint ? [ lastMatchedPoint, point ] : [ prevMatchedPoint, point ];
})), this.points = this.interpolatePoints.map((interpolate => {
const fromPoint = interpolate[0], toPoint = interpolate[1], newPoint = new Point(fromPoint.x, fromPoint.y, fromPoint.x1, fromPoint.y1);
return newPoint.defined = toPoint.defined, newPoint.context = toPoint.context, newPoint;
}));
}
onFirstRun() {
const lastClipRange = this.target.attribute.clipRange;
isValidNumber(lastClipRange * this.clipRange) && (this.clipRange *= lastClipRange);
}
onEnd(cb) {
cb ? super.onEnd(cb) : (this.to && commitAnimationStaticAttrs(this.target, Object.keys(this.to), this.animate, this.to),
super.onEnd());
}
applyPointTransientAttributes(attributes) {
const validAttrs = {};
Object.keys(attributes).forEach((key => {
this.animate.validAttr(key) && (validAttrs[key] = attributes[key]);
})), Object.keys(validAttrs).length && (applyAnimationFrameAttributes(this.target, validAttrs),
this.target.addUpdatePositionTag(), this.target.addUpdateShapeAndBoundsTag());
}
onUpdate(end, ratio, out) {
if (end) this.applyPointTransientAttributes(this.to); else {
if (this.points = this.points.map(((point, index) => {
const newPoint = pointInterpolation(this.interpolatePoints[index][0], this.interpolatePoints[index][1], ratio);
return newPoint.context = point.context, newPoint;
})), this.clipRange) {
if (this.shrinkClipRange) return void (end ? (out.points = this.toPoints, out.clipRange = 1) : (out.points = this.fromPoints,
out.clipRange = this.clipRange - (this.clipRange - this.shrinkClipRange) * ratio));
applyAnimationTransientAttributes(this.target, {
clipRange: this.clipRange + (1 - this.clipRange) * ratio
});
}
if (this.segmentsCache && this.to.segments) {
let start = 0;
const segments = this.to.segments.map(((segment, index) => {
const end = start + this.segmentsCache[index], points = this.points.slice(start, end);
return start = end, Object.assign(Object.assign({}, segment), {
points: points
});
}));
this.applyPointTransientAttributes({
segments: segments
});
} else this.applyPointTransientAttributes({
points: this.points
});
}
}
}
//# sourceMappingURL=tag-points.js.map