UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 6.56 kB
{"version":3,"file":"AnimationBase.mjs","names":[],"sources":["../../../../src/util/animation/AnimationBase.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport { getFabricWindow } from '../../env';\nimport { requestAnimFrame } from './AnimationFrameProvider';\nimport { runningAnimations } from './AnimationRegistry';\nimport { defaultEasing } from './easing';\nimport type {\n AnimationState,\n TAbortCallback,\n TBaseAnimationOptions,\n TEasingFunction,\n TOnAnimationChangeCallback,\n} from './types';\n\nconst defaultAbort = () => false;\n\nexport abstract class AnimationBase<\n T extends number | number[] = number | number[],\n> {\n declare readonly startValue: T;\n declare readonly endValue: T;\n declare readonly duration: number;\n declare readonly delay: number;\n\n declare protected readonly byValue: T;\n declare protected readonly easing: TEasingFunction<T>;\n\n declare private readonly _onStart: VoidFunction;\n declare private readonly _onChange: TOnAnimationChangeCallback<T>;\n declare private readonly _onComplete: TOnAnimationChangeCallback<T>;\n declare private readonly _abort: TAbortCallback<T>;\n\n /**\n * Used to register the animation to a target object\n * so that it can be cancelled within the object context\n */\n declare readonly target?: unknown;\n\n private _state: AnimationState = 'pending';\n /**\n * Time %, or the ratio of `timeElapsed / duration`\n * @see tick\n */\n durationProgress = 0;\n /**\n * Value %, or the ratio of `(currentValue - startValue) / (endValue - startValue)`\n */\n valueProgress = 0;\n /**\n * Current value\n */\n declare value: T;\n /**\n * Animation start time ms\n */\n declare private startTime: number;\n\n declare private timeout: number | null;\n\n constructor({\n startValue,\n byValue,\n duration = 500,\n delay = 0,\n easing = defaultEasing,\n onStart = noop,\n onChange = noop,\n onComplete = noop,\n abort = defaultAbort,\n target,\n }: TBaseAnimationOptions<T>) {\n this.tick = this.tick.bind(this);\n\n this.duration = duration;\n this.delay = delay;\n this.easing = easing;\n this._onStart = onStart;\n this._onChange = onChange;\n this._onComplete = onComplete;\n this._abort = abort;\n this.target = target;\n\n this.startValue = startValue;\n this.byValue = byValue;\n this.value = this.startValue;\n this.endValue = Object.freeze(this.calculate(this.duration).value);\n }\n\n get state() {\n return this._state;\n }\n\n isDone() {\n return this._state === 'aborted' || this._state === 'completed';\n }\n\n /**\n * Calculate the current value based on the easing parameters\n * @param timeElapsed in ms\n * @protected\n */\n protected abstract calculate(timeElapsed: number): {\n value: T;\n valueProgress: number;\n };\n\n start() {\n const firstTick: FrameRequestCallback = (timestamp) => {\n if (this._state !== 'pending') return;\n this.startTime = timestamp || +new Date();\n this._state = 'running';\n this._onStart();\n this.tick(this.startTime);\n };\n\n this.register();\n\n // setTimeout(cb, 0) will run cb on the next frame, causing a delay\n // we don't want that\n if (this.delay > 0) {\n this.timeout = getFabricWindow().setTimeout(\n () => requestAnimFrame(firstTick),\n this.delay,\n );\n } else {\n requestAnimFrame(firstTick);\n }\n }\n\n private tick(t: number) {\n const durationMs = (t || +new Date()) - this.startTime;\n const boundDurationMs = Math.min(durationMs, this.duration);\n this.durationProgress = boundDurationMs / this.duration;\n const { value, valueProgress } = this.calculate(boundDurationMs);\n this.value = Object.freeze(value);\n this.valueProgress = valueProgress;\n\n if (this._state === 'aborted') {\n return;\n } else if (\n this._abort(this.value, this.valueProgress, this.durationProgress)\n ) {\n this._state = 'aborted';\n this.unregister();\n } else if (durationMs >= this.duration) {\n this.durationProgress = this.valueProgress = 1;\n this._onChange(this.endValue, this.valueProgress, this.durationProgress);\n this._state = 'completed';\n this._onComplete(\n this.endValue,\n this.valueProgress,\n this.durationProgress,\n );\n this.unregister();\n this.timeout = null;\n } else {\n this._onChange(this.value, this.valueProgress, this.durationProgress);\n requestAnimFrame(this.tick);\n }\n }\n\n private register() {\n runningAnimations.push(this as unknown as AnimationBase);\n }\n\n private unregister() {\n runningAnimations.remove(this as unknown as AnimationBase);\n }\n\n abort() {\n this._state = 'aborted';\n this.unregister();\n\n this.timeout && getFabricWindow().clearTimeout(this.timeout);\n }\n}\n"],"mappings":";;;;;;;AAaA,MAAM,qBAAqB;AAE3B,IAAsB,gBAAtB,MAEE;CAyCA,YAAY,EACV,YACA,SACA,WAAW,KACX,QAAQ,GACR,SAAS,eACT,UAAU,MACV,WAAW,MACX,aAAa,MACb,QAAQ,cACR,UAC2B;wBAhCrB,UAAyB,UAAU;;;;;;;GAK3C;GAAmB;GAAE;;;;;;GAIrB;GAAgB;GAAE;AAwBhB,OAAK,OAAO,KAAK,KAAK,KAAK,KAAK;AAEhC,OAAK,WAAW;AAChB,OAAK,QAAQ;AACb,OAAK,SAAS;AACd,OAAK,WAAW;AAChB,OAAK,YAAY;AACjB,OAAK,cAAc;AACnB,OAAK,SAAS;AACd,OAAK,SAAS;AAEd,OAAK,aAAa;AAClB,OAAK,UAAU;AACf,OAAK,QAAQ,KAAK;AAClB,OAAK,WAAW,OAAO,OAAO,KAAK,UAAU,KAAK,SAAS,CAAC,MAAM;;CAGpE,IAAI,QAAQ;AACV,SAAO,KAAK;;CAGd,SAAS;AACP,SAAO,KAAK,WAAW,aAAa,KAAK,WAAW;;CAatD,QAAQ;EACN,MAAM,aAAmC,cAAc;AACrD,OAAI,KAAK,WAAW,UAAW;AAC/B,QAAK,YAAY,aAAa,iBAAC,IAAI,MAAM;AACzC,QAAK,SAAS;AACd,QAAK,UAAU;AACf,QAAK,KAAK,KAAK,UAAU;;AAG3B,OAAK,UAAU;AAIf,MAAI,KAAK,QAAQ,EACf,MAAK,UAAU,iBAAiB,CAAC,iBACzB,iBAAiB,UAAU,EACjC,KAAK,MACN;MAED,kBAAiB,UAAU;;CAI/B,KAAa,GAAW;EACtB,MAAM,cAAc,KAAK,iBAAC,IAAI,MAAM,IAAI,KAAK;EAC7C,MAAM,kBAAkB,KAAK,IAAI,YAAY,KAAK,SAAS;AAC3D,OAAK,mBAAmB,kBAAkB,KAAK;EAC/C,MAAM,EAAE,OAAO,kBAAkB,KAAK,UAAU,gBAAgB;AAChE,OAAK,QAAQ,OAAO,OAAO,MAAM;AACjC,OAAK,gBAAgB;AAErB,MAAI,KAAK,WAAW,UAClB;WAEA,KAAK,OAAO,KAAK,OAAO,KAAK,eAAe,KAAK,iBAAiB,EAClE;AACA,QAAK,SAAS;AACd,QAAK,YAAY;aACR,cAAc,KAAK,UAAU;AACtC,QAAK,mBAAmB,KAAK,gBAAgB;AAC7C,QAAK,UAAU,KAAK,UAAU,KAAK,eAAe,KAAK,iBAAiB;AACxE,QAAK,SAAS;AACd,QAAK,YACH,KAAK,UACL,KAAK,eACL,KAAK,iBACN;AACD,QAAK,YAAY;AACjB,QAAK,UAAU;SACV;AACL,QAAK,UAAU,KAAK,OAAO,KAAK,eAAe,KAAK,iBAAiB;AACrE,oBAAiB,KAAK,KAAK;;;CAI/B,WAAmB;AACjB,oBAAkB,KAAK,KAAiC;;CAG1D,aAAqB;AACnB,oBAAkB,OAAO,KAAiC;;CAG5D,QAAQ;AACN,OAAK,SAAS;AACd,OAAK,YAAY;AAEjB,OAAK,WAAW,iBAAiB,CAAC,aAAa,KAAK,QAAQ"}