Files
Unify/framework/client/animation/animationManager.js
2025-12-25 11:16:59 +01:00

455 lines
7.3 KiB
JavaScript

/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import animation from "./animation.js";
export default class animationManager{
id = 0;
start = 0;
animations = new Array();
element = document.querySelector(".test");
promises = new Array();
eventListener;
constructor() {
this.id = document.animationID++;
}
createAnimation( name ) {
var newAnimation = new animation();
newAnimation.animationManager = this
newAnimation.id = document.keyframeID++;
newAnimation.name = name + newAnimation.id;
newAnimation.element = this.element;
newAnimation.created = false;
this.animations[ newAnimation.name ] = newAnimation;
this.createListeners( newAnimation );
return newAnimation;
}
getAnimationClassName() {
return "keyFrameAnimation" + this.id;
}
createListeners( animation ) {
if( !animation.direction ) {
animation.__direction = "normal"
} else {
animation.__direction = animation.direction;
}
var that = this;
animation.__defineSetter__( "direction", function( value ){
animation.__direction = value;
var animationManager = animation.animationManager;
var source = that.composeCss();
animation.writeStyleToDOM( source );
});
animation.__defineGetter__( "direction", function(){
return animation.__direction;
});
}
composeKeyFrameCss( source ) {
var animations = this.animations;
for ( var i in animations ) {
var currentAnimation = animations[i];
//if( !currentAnimation.active ) {
source += "@keyframes " + currentAnimation.name + "{ \n";
var keyFrames = currentAnimation.keyFrames;
for (var i = 0; i < keyFrames.length; i++) {
var currentKeyFrame = keyFrames[i];
source += "\t" + currentKeyFrame.percent + "% {";
source += currentKeyFrame.composeCss();
source += "}\n";
}
source += "} \n";
currentAnimation.created = true;
//}
}
return source;
}
composeAnimationCss( source ) {
var names = new Array();
var durations = new Array();
var interationCounts = new Array();
var fillModes = new Array();
var directions = new Array();
var animations = this.animations;
for ( var i in animations ) {
var currentAnimation = animations[i];
if( currentAnimation.active ) {
if( currentAnimation.duration ) {
names.push( currentAnimation.name );
durations.push( currentAnimation.duration );
directions.push( currentAnimation.direction );
if( !currentAnimation.iterationCount ) {
currentAnimation.iterationCount = 1;
}
interationCounts.push( currentAnimation.iterationCount );
if( !currentAnimation.fillMode ) {
currentAnimation.fillMode = "none";
}
fillModes.push( currentAnimation.fillMode );
}
}
}
source += ".keyFrameAnimation" + this.id + "{\n";
source += "\tanimation-name: " + names.join(",") + ";\n";
source += "\tanimation-duration: " + durations.join(",") + ";\n";
source += "\tanimation-iteration-count: " + interationCounts.join(",") + ";\n";
source += "\tanimation-fill-mode: " + fillModes.join(",") + ";\n";
source += "\tanimation-direction: " + directions.join(",") + ";\n";
source += "}";
return source;
}
composeCss() {
var source = "";
source += this.composeKeyFrameCss( source );
source += this.composeAnimationCss( source );
return source;
}
addPromise( promiseObject ) {
this.promises[ promiseObject.id ] = promiseObject;
}
getPromiseByID( id ) {
return this.promises[ id ];
}
createPromiseFunction( animationID ) {
var that = this;
function promiseFunction( resolveFunction ){
var promiseObject = {};
promiseObject.id = animationID;
promiseObject.resolve = resolveFunction;
that.addPromise( promiseObject );
}
return promiseFunction;
}
attach( object ){
object.__proto__.animate = this.createCallback( object );
var animationManager = this;
object.createAnimation = function( name ) {
return object.animationManager.createAnimation( name );
}
this.element = object.element;
}
createCallback( object ) {
object.animationManager.object = object;
return async function( from, to, callback ) {
return object.animationManager.animate( from, to, callback );
}
}
async animate( from, to, callback, firstTick = true, animationID, value = false, start = false ) {
var object = this.object;
if( firstTick ) {
animationID = document.animationID++;
}
var sign = Math.sign( from - to );
var stop = false;
if( sign > 0) {
value = from - value;
if( value < to ) {
var stop = true;
}
} else {
value = from + value;
if( value > to ) {
var stop = true;
}
}
if( firstTick ) {
this.object[ "animationCallback" + animationID ] = callback;
}
if( !stop ) {
this.object[ "animationCallback" + animationID ]( value );
window.requestAnimationFrame( function( timestamp ) {
if( !start ) {
start = timestamp;
}
var progress = ( timestamp - start );
object.animationManager.animate( from, to, callback, false, animationID, progress, start );
});
} else {
var promise = this.getPromiseByID( animationID );
promise.resolve();
}
if( firstTick ) {
this.object[ "animationCallback" + animationID ]( value );
var promiseFunction = this.createPromiseFunction( animationID );
await new Promise( promiseFunction )
return true;
}
}
createEventListener() {
var that = this;
if( this.element.keyFrameEventListener ) {
canvas.removeEventListener('click', this.element.keyFrameEventListener);
}
this.element.keyFrameEventListener = this.element.addEventListener("animationend", async function( event ) {
var animations = that.animations;
var animationName = event.animationName;
//console.log(animationName, that.promises);
//console.log(animations, animationName)
var currentAnimation = animations[ animationName ];
console.log("turn off animation", currentAnimation);
currentAnimation.active = false;
//console.log("promise with animationName", animationName, "and animationID", currentAnimation.animationID, "removed");
if( currentAnimation ) {
var promise = that.promises[currentAnimation.id];
if( promise ) {
promise.resolve();
} else {
return false;
}
}
//console.log("ended animation", currentAnimation);
that.promises.splice( currentAnimation.id, 1, false )
for (var i = 0; i < that.promises.length; i++) {
if( that.promises[i] ) {
return false
}
}
//console.log("all promises are resolved resetting animation");
//that.resetAnimation();
var animationClassName = that.getAnimationClassName();
that.element.classList.remove(animationClassName);
}, false);
return true;
}
resetAnimation() {
//if( this.element.classList.contains("keyFrameAnimations") ) {
this.element.classList.remove("keyFrameAnimations")
//}
}
}