/* 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") //} } }