algoframe
Version:
A TypeScript comprehensive and modulated libary for doing algebraic animation with requestAnimatioFrame natively, even with Bezier and Sequences
148 lines (147 loc) • 6.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Animate = exports.Sequence = exports.sensibility = void 0;
const timeline_1 = require("./timeline");
Object.defineProperty(exports, "Sequence", { enumerable: true, get: function () { return timeline_1.Sequence; } });
const utils_1 = require("./utils");
exports.sensibility = 0.9;
class Animate {
constructor(options) {
// Frame properties
this.frame = new utils_1.Framer();
this.control = new utils_1.Controller();
this.progress = 0;
// Engine
this.engine = new utils_1.Animator(this);
const { sequence, easing, controls, timing } = options;
this.engine.easing = (0, utils_1.passPreset)(easing ? easing : 'linear');
this.frame.sequence = sequence;
if (controls === null || controls === void 0 ? void 0 : controls.FPS)
this.frame.FPS = controls.FPS; // also implicitily declares Framer._precision
if (controls === null || controls === void 0 ? void 0 : controls.loop)
this.control.loop = controls.loop;
this.frame.start.time = (timing === null || timing === void 0 ? void 0 : timing.delay) || 0;
this.frame.duration = (timing === null || timing === void 0 ? void 0 : timing.duration) || sequence.duration;
}
finally(callback) {
this.control.finally = callback;
return this;
}
break() {
this.control.stop = false;
return this;
}
precision(value) {
this.frame.precision = value;
return this;
}
run(callback) {
if (this.frame.sequence.duration !== this.frame.duration)
this.frame.duration = this.frame.sequence.duration;
let condition, seg;
if (callback) {
this.control.callback = callback;
}
// if (!this.control.callback)
// throw new Error('Main callback is required for the animation');
this.frame.last.time = new utils_1.Refresher();
this.frame.last.frameRate = this.frame.last.frameRate
? this.frame.last.frameRate
: new utils_1.Refresher(this.frame.precision);
function refresh(timestamp) {
if (this.control.completed) {
this.frame.frame = -1;
this.frame.start.animationTime = timestamp;
this.control.completed = false;
}
if (this.frame._FPS) {
seg = Math.floor((timestamp - this.frame.start.time) / this.frame.delay);
condition = Boolean(seg > this.frame.count);
}
else {
condition = true;
}
this.frame.last.time.refresh(timestamp);
}
function animate(timestamp) {
var _a, _b, _c, _d, _e, _f;
refresh.call(this, timestamp);
let runtime = null, relativeProgress = null, easedProgress = null;
this.control.sent = false;
const send = () => {
var _a, _b, _c, _d;
this.control.sent = true;
this.frame.value = this.frame.sequence.test(Math.min(easedProgress, 1));
if (this.frame.value > 100) {
debugger;
}
// TODO: Add a recursvie callback inside Sequence
(_b = (_a = this.frame.sequence).callback) === null || _b === void 0 ? void 0 : _b.call(_a, this.frame.stats());
// console.log(this.frame.sequence) // END
(_d = (_c = this.control).callback) === null || _d === void 0 ? void 0 : _d.call(_c, this.frame.stats());
};
// console.log(this.frame.start.time);
if (!this.frame.start.animationTime && this.frame.start.time === 0) {
this.frame.start.animationTime = timestamp;
}
else if (this.frame.start.time > 0) {
this.frame.start.animationTime = timestamp;
let last = 0;
if (typeof this.frame.last.time.last === 'number') {
last = this.frame.last.time.last;
}
this.frame.start.time =
this.frame.start.time - last < last * exports.sensibility
? 0
: this.frame.start.time - last;
requestAnimationFrame(animate.bind(this));
return;
}
if (this.frame.start.animationTime) {
// console.log(this.frame.start.animationTime - timestamp);
runtime = timestamp - this.frame.start.animationTime;
relativeProgress = runtime / this.frame.duration;
easedProgress = this.engine.easing(relativeProgress);
this.progress = Math.min(easedProgress, 1);
this.frame.progress = Math.min(easedProgress, 1);
}
if (condition) {
this.frame.count = seg;
this.frame.frame++;
this.frame.last.frameRate.refresh(timestamp);
send();
}
if (!this.control.stop) {
if (typeof runtime === 'number' && runtime < this.frame.duration) {
requestAnimationFrame(animate.bind(this));
}
else if (runtime &&
runtime +
(typeof this.frame.last.time.last === 'number'
? this.frame.last.time.last
: 0) >
this.frame.duration) {
this.frame.frame++;
send();
this.control.completed = true;
if (this.control.loop)
requestAnimationFrame(animate.bind(this));
(_b = (_a = this.control).finally) === null || _b === void 0 ? void 0 : _b.call(_a);
// this.frame.sequence.ofinallyCallback?.();
}
else if (!this.control.completed) {
this.control.completed = true;
if (this.control.loop)
requestAnimationFrame(animate.bind(this));
(_d = (_c = this.control).finally) === null || _d === void 0 ? void 0 : _d.call(_c);
(_f = (_e = this.frame.sequence).ofinallyCallback) === null || _f === void 0 ? void 0 : _f.call(_e);
}
}
if (this.frame.frame === 0)
this.control._start();
}
requestAnimationFrame(animate.bind(this));
return this;
}
}
exports.Animate = Animate;