0

I am currently working on a CMS project to create perspective objects using CSS transform properties (scale, rotate, translate...) in 3d: XYZ. When an object is created it has these characteristics in its matrix3d(-16 values-) returned by window.getComputedStyle(element) -> style['transform'] The next step is to create animations: through a set of input[range], the user can modify these objects' characteristics and get their final state once the animation is finished. It works very well. The question now is to create the complete dynamic CSS system, object by object.

I have its matrix1 (initial matrix3d) and its matrix2 (final matrix3d). By executing

@keyframes anim { 
    from { transform: matrix1 } 
    to { transform: matrix2; } 
}

document.getElementById('object').style.animation = 'anim 2s linear';

it should work on its own... The prob is to create the CSS instruction. Using:

document.styleSheets[0].insertRule('
        @keyframes anim { 
            from { transform: matrix1 } 
            to { transform: matrix2; } 
        }'
);

works well but once it's created in the main CSS file, if user modifies the matrix2 I can't rewrite the same instruction twice...

My idea is to create a CSS file for each objet on the server then import it with JS: if user is satisfied I keep it, and if not I remove it and create a new one with its new matrix2.

the advantage is that I can keep the word 'anim' without risking conflict between objects since each will call its own CSS (i.e 'object1.css').

Is this the best way to proceed or do you recommend another one?

Another question: despite my research I can't find what the 16 values of matrix3d correspond to. Translate XYZ is in [12], [13], [14] but I don't have them all. If you know a more explicit resource than https://developer.mozilla.org/fr/docs/Web/CSS/transform-function/matrix3d() it may help.

Quasipickle
  • 4,383
  • 1
  • 31
  • 53
Wolden
  • 195
  • 1
  • 12
  • updating CSS seems possible using `var(--variable);` see Will answer in – Wolden Jan 20 '22 at 20:17
  • I found the answer here ideal: https://stackoverflow.com/questions/1720320/how-to-dynamically-create-css-class-in-javascript-and-apply – Ger Nov 23 '22 at 06:18

1 Answers1

0

Finally found the solution... maybe not the best but it works.

We create the first matrix3D (object in its initial state):

getObjectValues('objID', 0); // 0 for matrix1

The function

function getObjectValues(div, n){ // 0 for matrix1, 1 for matrix2

   let element = document.getElementById(div);

   let myTransform = window.getComputedStyle(element,null)
   let matrix = myTransform.getPropertyValue("-webkit-transform");

   if (matrix === 'none' || typeof matrix === 'undefined') {

      // native HTML objects (as divs) are not in a 3D dimension space
      // if necessary we create its 3D environment

      element.style.transform = 'translateZ(1px)';
      getObjectValues(div, n); // then reload the function
   }
   else { 
      matrixObj[n] = matrix; 
   }
} 

 // Array matrixObj at this step:
 [0] -> matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)

After playing with the different input type="range" (for position, rotation, ... in XYZ dimension) we create the second matrix3D (final state) by clicking on the "TEST" button, which calls

 getObjectValues('objID', 1); // 1 for matrix2

 // Array matrixObj at this step:
 [0] -> matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)
 [1] -> matrix3d(0.945519, 0, -0.325568, 0, 0, 1, 0, 0, 0.325568, 0, 0.945519, 0, 0, 0, -48, 1)

Now the trick: we create a pseudo CSS sheet called "anim-update"

  includeCSS("anim-update");
  let styleSheet = document.getElementById("anim-update");

  // the function

  function includeCSS(css) {
      let head = document.getElementsByTagName('head')[0];
      let sheet = document.createElement('style');
      sheet.setAttribute('id',css);
      sheet.setAttribute('rel', 'stylesheet');
      sheet.setAttribute('type', 'text/css');
      head.appendChild(sheet);
  }

Once its done we play these 3 sequences:

    let delay = 2;  // duration

    // 1. returns the object to its initial state

    setTimeout(function(){
        document.getElementById(div).style.transform = matrixObj[0]; 
    },100);

    // 2. play the scenario
    
    setTimeout(function(){ 
        styleSheet.innerHTML = '@keyframes anim { 
           from { transform: '+matrixObj[n][0]+' } 
           to { transform: '+matrixObj[n][1]+' } 
        }';
        document.getElementById(div).style.animation = 'anim '+delay+'s linear';
    },500);

    // 3. removes the temporary CSS at the end of the animation

    setTimeout(function(){
         document.getElementById('anim-update').outerHTML = ""; 
         delete document.getElementById('anim-update');
    },500+2000); // +2 seconds -> delay*1000

In this way User can change the final state of the object as much as he wants until he gets the desired animation, which he checks by clicking on the "TEST" button. A "SAVE" button retrieves the data from matrixObj and saves the 2 matrix values. Then move to the next object.

Wolden
  • 195
  • 1
  • 12