UNPKG

@visactor/vrender-core

Version:
403 lines (392 loc) 17.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.SubAnimate = exports.Animate = exports.CbAnimate = exports.ACustomAnimate = void 0; const enums_1 = require("../common/enums"), easing_1 = require("./easing"), vutils_1 = require("@visactor/vutils"), timeline_1 = require("./timeline"), generator_1 = require("../common/generator"); class ACustomAnimate { constructor(from, to, duration, easing, params) { this.from = from, this.to = to, this.duration = duration, this.easing = easing, this.params = params, this.updateCount = 0; } bind(target, subAni) { this.target = target, this.subAnimate = subAni, this.onBind(); } onBind() {} onFirstRun() {} onStart() {} onEnd() {} getEndProps() { return this.to; } getFromProps() { return this.from; } getMergedEndProps() { var _a; const thisEndProps = this.getEndProps(); return thisEndProps ? this._endProps === thisEndProps ? this._mergedEndProps : (this._endProps = thisEndProps, void (this._mergedEndProps = Object.assign({}, null !== (_a = this.step.prev.getLastProps()) && void 0 !== _a ? _a : {}, thisEndProps))) : this.step.prev ? this.step.prev.getLastProps() : thisEndProps; } update(end, ratio, out) { if (0 === this.updateCount) { this.onFirstRun(); const props = this.step.getLastProps(); Object.keys(props).forEach((k => { this.subAnimate.animate.validAttr(k) && (out[k] = props[k]); })); } this.updateCount += 1, this.onUpdate(end, ratio, out), end && this.onEnd(); } } exports.ACustomAnimate = ACustomAnimate; class CbAnimate extends ACustomAnimate { constructor(cb) { super(null, null, 0, "linear"), this.cb = cb; } onUpdate(end, ratio, out) {} onStart() { this.cb(); } } exports.CbAnimate = CbAnimate; class Animate { constructor(id = generator_1.Generator.GenAutoIncrementId(), timeline = timeline_1.defaultTimeline, slience) { this.id = id, this.timeline = timeline || timeline_1.defaultTimeline, this.status = enums_1.AnimateStatus.INITIAL, this.tailAnimate = new SubAnimate(this), this.subAnimates = [ this.tailAnimate ], this.timeScale = 1, this.rawPosition = -1, this._startTime = 0, this._duringTime = 0, this.timeline.addAnimate(this), this.slience = slience; } setTimeline(timeline) { timeline !== this.timeline && (this.timeline.removeAnimate(this, !1), timeline.addAnimate(this)); } getStartTime() { return this._startTime; } getDuration() { return this.subAnimates.reduce(((t, subAnimate) => t + subAnimate.totalDuration), 0); } after(animate) { const t = animate.getDuration(); return this._startTime = t, this; } afterAll(list) { let maxT = -1 / 0; return list.forEach((a => { maxT = (0, vutils_1.max)(a.getDuration(), maxT); })), this._startTime = maxT, this; } parallel(animate) { return this._startTime = animate.getStartTime(), this; } static AddInterpolate(name, cb) { Animate.interpolateMap.set(name, cb); } play(customAnimate) { if (this.tailAnimate.play(customAnimate), this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return 1 === this.subAnimates.length && this.tailAnimate.totalDuration === customAnimate.duration && this.trySetAttribute(customAnimate.getFromProps(), customAnimate.mode), this; } trySetAttribute(attr, mode = Animate.mode) { attr && mode & enums_1.AnimateMode.SET_ATTR_IMMEDIATELY && this.target.setAttributes && this.target.setAttributes(attr, !1, { type: enums_1.AttributeUpdateType.ANIMATE_PLAY }); } runCb(cb) { const customAnimate = new CbAnimate((() => { cb(this, customAnimate.step.prev); })); return this.tailAnimate.play(customAnimate), this; } customInterpolate(key, ratio, from, to, target, ret) { const func = Animate.interpolateMap.get(key) || Animate.interpolateMap.get(""); return !!func && func(key, ratio, from, to, target, ret); } pause() { this.status === enums_1.AnimateStatus.RUNNING && (this.status = enums_1.AnimateStatus.PAUSED); } resume() { this.status === enums_1.AnimateStatus.PAUSED && (this.status = enums_1.AnimateStatus.RUNNING); } to(props, duration, easing, params) { if (this.tailAnimate.to(props, duration, easing, params), this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } from(props, duration, easing, params) { if (this.tailAnimate.from(props, duration, easing, params), this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } wait(duration) { if (this.tailAnimate.wait(duration), this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } startAt(t) { if (this.tailAnimate.startAt(t), this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } loop(l) { if (this.tailAnimate.loop = l, this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } reversed(r) { if (this.tailAnimate.reversed = r, this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } bounce(b) { if (this.tailAnimate.bounce = b, this.target) { const stage = this.target.stage; stage && stage.renderNextFrame(); } return this; } subAnimate() { const sa = new SubAnimate(this, this.tailAnimate); return this.tailAnimate = sa, this.subAnimates.push(sa), sa.bind(this.target), this; } getStartProps() { return this.subAnimates[0].getStartProps(); } getEndProps() { return this.tailAnimate.getEndProps(); } depreventAttr(key) { this._preventAttrs && this._preventAttrs.delete(key); } preventAttr(key) { this._preventAttrs || (this._preventAttrs = new Set), this._preventAttrs.add(key); } preventAttrs(keys) { keys.forEach((key => this.preventAttr(key))); } validAttr(key) { return !this._preventAttrs || !this._preventAttrs.has(key); } bind(target) { return this.target = target, this.target.onAnimateBind && !this.slience && this.target.onAnimateBind(this), this.subAnimates.forEach((sa => { sa.bind(target); })), this; } advance(delta) { if (this._duringTime < this._startTime) { if (this._duringTime + delta * this.timeScale < this._startTime) return void (this._duringTime += delta * this.timeScale); delta = this._duringTime + delta * this.timeScale - this._startTime, this._duringTime = this._startTime; } this.status === enums_1.AnimateStatus.INITIAL && (this.status = enums_1.AnimateStatus.RUNNING, this._onStart && this._onStart.forEach((cb => cb()))); this.setPosition(Math.max(this.rawPosition, 0) + delta * this.timeScale) && this.status === enums_1.AnimateStatus.RUNNING && (this.status = enums_1.AnimateStatus.END, this._onEnd && this._onEnd.forEach((cb => cb()))); } setPosition(rawPosition) { let sa, d = 0; const prevRawPos = this.rawPosition, maxRawPos = this.subAnimates.reduce(((a, b) => a + b.totalDuration), 0); rawPosition < 0 && (rawPosition = 0); const end = rawPosition >= maxRawPos; if (end && (rawPosition = maxRawPos), rawPosition === prevRawPos) return end; for (let i = 0; i < this.subAnimates.length && (sa = this.subAnimates[i], !(d + sa.totalDuration >= rawPosition)); i++) d += sa.totalDuration, sa = void 0; return this.rawPosition = rawPosition, sa.setPosition(rawPosition - d), end; } onStart(cb) { this._onStart || (this._onStart = []), this._onStart.push(cb); } onEnd(cb) { this._onEnd || (this._onEnd = []), this._onEnd.push(cb); } onRemove(cb) { this._onRemove || (this._onRemove = []), this._onRemove.push(cb); } onFrame(cb) { this._onFrame || (this._onFrame = []), this._onFrame.push(cb); } release() { this.status = enums_1.AnimateStatus.END; } stop(nextVal) { nextVal || this.target.onStop(), "start" === nextVal ? this.target.onStop(this.getStartProps()) : "end" === nextVal ? this.target.onStop(this.getEndProps()) : this.target.onStop(nextVal), this.release(); } } exports.Animate = Animate, Animate.mode = enums_1.AnimateMode.NORMAL, Animate.interpolateMap = new Map; class SubAnimate { get totalDuration() { return this.calcAttr(), this._totalDuration + this._startAt; } constructor(animate, lastSubAnimate) { this.rawPosition = -1, this.position = 0, this.loop = 0, this.duration = 0, this.animate = animate, this.stepHead = new Step(0, 0, lastSubAnimate ? Object.assign({}, lastSubAnimate.stepTail.props) : {}), this.stepTail = this.stepHead, this.dirty = !0, this._startAt = 0; } calcAttr() { this.dirty && (this._totalDuration = this.duration * (this.loop + 1)); } bind(target) { return this.target = target, this; } play(customAnimate) { let duration = customAnimate.duration; (null == duration || duration < 0) && (duration = 0); const easing = customAnimate.easing, easingFunc = "string" == typeof easing ? easing_1.Easing[easing] : easing, step = this._addStep(duration, null, easingFunc); return step.type = enums_1.AnimateStepType.customAnimate, this._appendProps(customAnimate.getEndProps(), step, !1), this._appendCustomAnimate(customAnimate, step), this; } to(props, duration, easing, params) { (null == duration || duration < 0) && (duration = 0); const easingFunc = "string" == typeof easing ? easing_1.Easing[easing] : easing, step = this._addStep(duration, null, easingFunc); return step.type = enums_1.AnimateStepType.to, this._appendProps(props, step, !!params && params.tempProps), step.propKeys || (step.propKeys = Object.keys(step.props)), params && params.noPreventAttrs || this.target.animates && this.target.animates.forEach((a => { a.id !== this.animate.id && a.preventAttrs(step.propKeys); })), this; } from(props, duration, easing, params) { this.to(props, 0, easing, params); const toProps = {}; this.stepTail.propKeys || (this.stepTail.propKeys = Object.keys(this.stepTail.props)), this.stepTail.propKeys.forEach((k => { toProps[k] = this.getLastPropByName(k, this.stepTail); })), this.to(toProps, duration, easing, params), this.stepTail.type = enums_1.AnimateStepType.from; } startAt(t) { return t < 0 && (t = 0), this._startAt = t, this; } getStartProps() { var _a; return null === (_a = this.stepHead) || void 0 === _a ? void 0 : _a.props; } getEndProps() { return this.stepTail.props; } getLastStep() { return this._lastStep; } wait(duration) { if (duration > 0) { const step = this._addStep(+duration, null); step.type = enums_1.AnimateStepType.wait, step.prev.customAnimate ? step.props = step.prev.customAnimate.getEndProps() : step.props = step.prev.props, this.target.onAddStep && this.target.onAddStep(step); } return this; } _addStep(duration, props, easingFunc) { const step = new Step(this.duration, duration, props, easingFunc); return this.duration += duration, this.stepTail.append(step), this.stepTail = step, step; } _appendProps(props, step, tempProps) { step.props = tempProps ? props : Object.assign({}, props); let lastStep = step.prev; const _props = step.props; for (step.propKeys || (step.propKeys = Object.keys(step.props)), step.propKeys.forEach((k => { void 0 === step.props[k] && (step.props[k] = this.target.getDefaultAttribute(k)); })); lastStep.prev; ) lastStep.props && (lastStep.propKeys || (lastStep.propKeys = Object.keys(lastStep.props)), lastStep.propKeys.forEach((key => { void 0 === _props[key] && (_props[key] = lastStep.props[key]); }))), step.propKeys = Object.keys(step.props), lastStep = lastStep.prev; const initProps = this.stepHead.props; step.propKeys || (step.propKeys = Object.keys(_props)), step.propKeys.forEach((key => { if (void 0 === initProps[key]) { const parentAnimateInitProps = this.animate.getStartProps(); initProps[key] = parentAnimateInitProps[key] = this.target.getComputedAttribute(key); } })), this.target.onAddStep && this.target.onAddStep(step); } _appendCustomAnimate(customAnimate, step) { step.customAnimate = customAnimate, customAnimate.step = step, customAnimate.bind(this.target, this); } setPosition(rawPosition) { var _a; const d = this.duration, loopCount = this.loop, prevRawPos = this.rawPosition; let loop, position, end = !1; const startAt = null !== (_a = this._startAt) && void 0 !== _a ? _a : 0; if (rawPosition < 0 && (rawPosition = 0), rawPosition < startAt) return this.rawPosition = rawPosition, !1; if (rawPosition -= startAt, d <= 0 && (end = !0, d < 0)) return end; if (loop = Math.floor(rawPosition / d), position = rawPosition - loop * d, end = rawPosition >= loopCount * d + d, end && (position = d, loop = loopCount, rawPosition = position * loop + d), rawPosition === prevRawPos) return end; const rev = !this.reversed != !(this.bounce && loop % 2); return rev && (position = d - position), this._deltaPosition = position - this.position, this.position = position, this.rawPosition = rawPosition + startAt, this.updatePosition(end, rev), end; } updatePosition(end, rev) { if (!this.stepHead) return; let step = this.stepHead.next; const position = this.position, duration = this.duration; if (this.target && step) { let stepNext = step.next; for (;stepNext && stepNext.position <= position; ) step = stepNext, stepNext = step.next; let ratio = end ? 0 === duration ? 1 : position / duration : (position - step.position) / step.duration; step.easing && (ratio = step.easing(ratio)), this.tryCallCustomAnimateLifeCycle(step, this._lastStep || (rev ? this.stepTail : this.stepHead), rev), this.updateTarget(step, ratio, end), this._lastStep = step, this.animate._onFrame && this.animate._onFrame.forEach((cb => cb(step, ratio))); } } tryCallCustomAnimateLifeCycle(step, lastStep, rev) { if (step !== lastStep) if (rev) { let _step = lastStep.prev; for (;_step && _step !== step; ) _step.customAnimate && (_step.customAnimate.onStart && _step.customAnimate.onStart(), _step.customAnimate.onEnd && _step.customAnimate.onEnd()), _step = step.prev; lastStep && lastStep.customAnimate && lastStep.customAnimate.onEnd && lastStep.customAnimate.onEnd(), step && step.customAnimate && step.customAnimate.onStart && step.customAnimate.onStart(); } else { let _step = lastStep.next; for (;_step && _step !== step; ) _step.customAnimate && (_step.customAnimate.onStart && _step.customAnimate.onStart(), _step.customAnimate.onEnd && _step.customAnimate.onEnd()), _step = _step.next; lastStep && lastStep.customAnimate && lastStep.customAnimate.onEnd && lastStep.customAnimate.onEnd(), step && step.customAnimate && step.customAnimate.onStart && step.customAnimate.onStart(); } } getLastPropByName(name, step) { let lastStep = step.prev; for (;lastStep; ) { if (lastStep.props && void 0 !== lastStep.props[name]) return lastStep.props[name]; if (lastStep.customAnimate) { const val = lastStep.customAnimate.getEndProps()[name]; if (void 0 !== val) return val; } lastStep = lastStep.prev; } return vutils_1.Logger.getInstance().warn("未知错误,step中找不到属性"), step.props[name]; } updateTarget(step, ratio, end) { null == step.props && null == step.customAnimate || this.target.onStep(this, this.animate, step, ratio, end); } } exports.SubAnimate = SubAnimate; class Step { constructor(position, duration, props, easing) { this.duration = duration, this.position = position, this.props = props, this.easing = easing; } append(step) { step.prev = this, step.next = this.next, this.next = step; } getLastProps() { let step = this.prev; for (;step; ) { if (step.props) return step.props; if (step.customAnimate) return step.customAnimate.getMergedEndProps(); step = step.prev; } return null; } } //# sourceMappingURL=animate.js.map