120 lines
3.7 KiB
JavaScript
120 lines
3.7 KiB
JavaScript
class MotionEngine {
|
|
constructor() {
|
|
const aq = [];
|
|
this.animationQueue = aq;
|
|
|
|
function calcValues(target, values, initial, k = 1, mode = 'offset') {
|
|
Object.entries(values).forEach(([key, value]) => {
|
|
if (value && typeof value === 'object') {
|
|
if (!target[key]) {
|
|
target[key] = {};
|
|
}
|
|
calcValues(target[key], value, initial[key], k, mode);
|
|
return;
|
|
}
|
|
if (mode == 'offset') {
|
|
target[key] = (initial[key] || 0) + value * k;
|
|
} else if (typeof (value) == 'function') {
|
|
let v = value(k, target[key]);
|
|
if (target[key] !== v){
|
|
target[key] = v;
|
|
}
|
|
} else {
|
|
target[key] = (initial[key] || 0) + (value - (initial[key] || 0)) * k;
|
|
}
|
|
});
|
|
return target;
|
|
}
|
|
|
|
// a = {o-object, a-attributes, t-time, f-finish event, d-delay, m-mode, r-repeat,
|
|
// rd-repeat the delay, rf-reset on finish, u-on update, s-scope, p-promise on finish}
|
|
this.add = function (a) {
|
|
a = Array.isArray(a) ? a : [a];
|
|
let r = [];
|
|
a.forEach(e => {
|
|
if (e.t == 0){
|
|
e.t = 1;
|
|
this.animate(e, 1)
|
|
}else{
|
|
aq.push(e);
|
|
}
|
|
if (e.p && !e.f){
|
|
r.push(new Promise( resolve=> e.f = resolve ))
|
|
}
|
|
});
|
|
if (r.length) return Promise.all(r);
|
|
};
|
|
|
|
this.clear = function (object, reset = false) {
|
|
for (var i = aq.length - 1; i >= 0; i--) {
|
|
if (object && aq[i].o == object || !object && (aq[i].ct == aq[i].t || aq[i].rr)) {
|
|
if (reset){
|
|
aq[i].ct = 0;
|
|
this.animate(aq[i], 0);
|
|
}
|
|
aq.splice(i, 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
this.clearAll = function(){
|
|
aq.splice(0, aq.length);
|
|
return;
|
|
}
|
|
|
|
this.remove = function (a) {
|
|
let idx = aq.indexOf(a);
|
|
if (idx > -1) {
|
|
a.ct = 0;
|
|
this.animate(a, 0);
|
|
aq.splice(idx, 1);
|
|
}
|
|
};
|
|
|
|
this.update = (delta) => {
|
|
if (aq.length) {
|
|
aq.forEach(e => this.animate(e, delta));
|
|
this.clear();
|
|
}
|
|
};
|
|
|
|
this.animate = function (e, t) {
|
|
if (e.d && (e.dt || 0) < e.d) {
|
|
e.dt = (e.dt || 0) + t;
|
|
return;
|
|
}
|
|
if (e.ct === undefined) {
|
|
e.ct = 0;
|
|
e.iv = calcValues({}, e.a, e.o, 0);
|
|
}
|
|
e.ct = e.ct + t;
|
|
if (e.ct > e.t) {
|
|
e.ct = e.t;
|
|
e.f?.();
|
|
if (e.rf){
|
|
e.ct = t = 0;
|
|
e.rr = true;
|
|
}
|
|
}
|
|
calcValues(e.o, e.a, e.iv, e.ct / e.t, e.m || 'value');
|
|
e.u?.();
|
|
if (e.ct == e.t && e.r) {
|
|
e.ct = e.m == 'offset' ? undefined : 0;
|
|
if (e.rd) {
|
|
e.dt = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
this.isActive = function (object) {
|
|
return aq.find(e => e.o == object);
|
|
};
|
|
|
|
this.isIdle = function (scope) {
|
|
if (!scope) return aq.length == 0;
|
|
return aq.filter(e => e.s == scope).length == 0
|
|
};
|
|
}
|
|
}
|
|
|
|
export {MotionEngine} |