First commit
This commit is contained in:
454
framework/client/animation/animationManager.js
Normal file
454
framework/client/animation/animationManager.js
Normal file
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
|
||||
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")
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user