fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
129 lines (121 loc) • 3.63 kB
JavaScript
import { defineProperty as _defineProperty } from '../../../_virtual/_rollupPluginBabelHelpers.mjs';
import { noop } from '../../constants.mjs';
import { requestAnimFrame } from './AnimationFrameProvider.mjs';
import { runningAnimations } from './AnimationRegistry.mjs';
import { defaultEasing } from './easing.mjs';
const defaultAbort = () => false;
class AnimationBase {
/**
* Current value
*/
/**
* Animation start time ms
*/
constructor(_ref) {
let {
startValue,
byValue,
duration = 500,
delay = 0,
easing = defaultEasing,
onStart = noop,
onChange = noop,
onComplete = noop,
abort = defaultAbort,
target
} = _ref;
/**
* Used to register the animation to a target object
* so that it can be cancelled within the object context
*/
_defineProperty(this, "_state", 'pending');
/**
* Time %, or the ratio of `timeElapsed / duration`
* @see tick
*/
_defineProperty(this, "durationProgress", 0);
/**
* Value %, or the ratio of `(currentValue - startValue) / (endValue - startValue)`
*/
_defineProperty(this, "valueProgress", 0);
this.tick = this.tick.bind(this);
this.duration = duration;
this.delay = delay;
this.easing = easing;
this._onStart = onStart;
this._onChange = onChange;
this._onComplete = onComplete;
this._abort = abort;
this.target = target;
this.startValue = startValue;
this.byValue = byValue;
this.value = this.startValue;
this.endValue = Object.freeze(this.calculate(this.duration).value);
}
get state() {
return this._state;
}
isDone() {
return this._state === 'aborted' || this._state === 'completed';
}
/**
* Calculate the current value based on the easing parameters
* @param timeElapsed in ms
* @protected
*/
start() {
const firstTick = timestamp => {
if (this._state !== 'pending') return;
this.startTime = timestamp || +new Date();
this._state = 'running';
this._onStart();
this.tick(this.startTime);
};
this.register();
// setTimeout(cb, 0) will run cb on the next frame, causing a delay
// we don't want that
if (this.delay > 0) {
setTimeout(() => requestAnimFrame(firstTick), this.delay);
} else {
requestAnimFrame(firstTick);
}
}
tick(t) {
const durationMs = (t || +new Date()) - this.startTime;
const boundDurationMs = Math.min(durationMs, this.duration);
this.durationProgress = boundDurationMs / this.duration;
const {
value,
valueProgress
} = this.calculate(boundDurationMs);
this.value = Object.freeze(value);
this.valueProgress = valueProgress;
if (this._state === 'aborted') {
return;
} else if (this._abort(this.value, this.valueProgress, this.durationProgress)) {
this._state = 'aborted';
this.unregister();
} else if (durationMs >= this.duration) {
this.durationProgress = this.valueProgress = 1;
this._onChange(this.endValue, this.valueProgress, this.durationProgress);
this._state = 'completed';
this._onComplete(this.endValue, this.valueProgress, this.durationProgress);
this.unregister();
} else {
this._onChange(this.value, this.valueProgress, this.durationProgress);
requestAnimFrame(this.tick);
}
}
register() {
runningAnimations.push(this);
}
unregister() {
runningAnimations.remove(this);
}
abort() {
this._state = 'aborted';
this.unregister();
}
}
export { AnimationBase };
//# sourceMappingURL=AnimationBase.mjs.map