First commit

This commit is contained in:
2025-12-25 11:16:59 +01:00
commit 0c5ca09a63
720 changed files with 329234 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
/*
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 keyFrame from "./animation.keyFrame.js";
export default class animation{
name;
element;
keyFrames = new Array();
animationManager;
duration;
createKeyFrame( percent ) {
var newKeyFrame = new keyFrame();
newKeyFrame.percent = percent;
this.keyFrames.push( newKeyFrame );
return newKeyFrame;
}
createPromiseFunction( id ) {
var that = this;
function promiseFunction( resolveFunction ){
var promiseObject = new Object;
promiseObject.id = id;
promiseObject.resolve = resolveFunction;
that.animationManager.addPromise( promiseObject );
}
return promiseFunction;
}
async stop() {
if( !this.element.classList.contains("keyFrameAnimations") ) {
var animationClassName = this.animationManager.getAnimationClassName();
this.element.classList.remove( animationClassName );
}
}
async pause() {
this.element.classList.add("pause-animation");
}
setDuration( duration ) {
this.duration = duration;
}
setDirection( direction ) {
this.direction = direction;
}
setIterationCount( iterationCount ) {
this.iterationCount = iterationCount;
}
setFillMode( fillMode ) {
this.fillMode = fillMode;
}
async play( duration ) {
if( this.element.classList.contains("pause-animation") ) {
this.element.classList.remove("pause-animation");
return true;
}
if( !this.element.classList.contains("keyFrameAnimations") ) {
var animationClassName = this.animationManager.getAnimationClassName();
this.element.classList.add( animationClassName );
}
if( duration ) {
this.duration = duration;
}
this.active = true;
var source = this.animationManager.composeCss();
this.writeStyleToDOM( source );
var promiseFunction = this.createPromiseFunction( this.id );
var promise = new Promise( promiseFunction );
this.animationManager.createEventListener();
await promise;
return true;
}
writeStyleToDOM( source ) {
var style = document.createElement("style")
style.type = 'text/css';
style.appendChild( document.createTextNode( source ) );
document.getElementsByTagName("head")[0].appendChild( style );
}
}

View File

@@ -0,0 +1,59 @@
/*
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 property from "./animation.property.js";
export default class keyFrame{
percent;
properties = new Array();
setProperty( name, value ) {
var newProperty = new property();
newProperty.name = name;
if(typeof value == "number") {
value += "px";
}
newProperty.value = value;
this.properties.push( newProperty );
}
composeCss() {
var properties = this.properties;
var propertyLines = "";
for (var i = 0; i < properties.length; i++) {
propertyLines += properties[i].composeCss();
}
return propertyLines;
}
}

View File

@@ -0,0 +1,38 @@
/*
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
*/
export default class property{
name;
value;
composeCss() {
var functionNames = new Array( "rotate", "translate", "scaleX", "scaleY", "scale", "skewX", "skewY", "skew", "matrix" );
if( functionNames.includes( this.name ) ) {
return "transform: " + this.name + "( " + this.value + " ); ";
} else {
return "\n " + this.name + " : " + this.value + ";\n";
}
}
}

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